发明内容
为了解决上述问题,本发明提出了一种图形数据库联机事务中事务回滚机制的实现方法,以实现事务的回滚机制。
本发明采用的技术方案如下:
一种图形数据库联机事务中事务回滚机制的实现方法,其特征在于:
联机事务处理自上而下分为三层:
最上层为暴露给外部调用程序的API;
中间层为事务逻辑控制层,按操作类别分为同步区与非同步区,同步区意味着在同一时间只能有一个操作进行,其他操作在进入同步区之间均处于等待状态,该机制利用Java语言的线程同步锁定特性实现,非同步区的操作则不受限制,在任何时间均可以进行;
最下层为存储数据的DataSet操作抽象层,在DataSet中,保存有联机事务自身的状态信息,以及数据的事务状态属性信息;
将图形数据库中联机事务的状态数据存储在名称为graphic_db_tx_def的数据集DataSet中,该DataSet的数据结构如下:
在图形数据库中每个Node均有一个数据集DataSet,该DataSet中缺省内置如下两个列:
用Relation描述Node与Node之间的关系,每一个Relation均有一个全局唯一的名称、一个源Node、一个目标Node,由源Node到目标Node的方向,称之为正向,由目标Node到起始Node的方向称之为反向,将每一个Relation的定义信息保存在名称为graphic_db_relation_def的DataSet中,该DataSet的数据结构如下:
列名称 |
数据类型 |
说明 |
relation_id |
Number |
全局唯一的ID |
name |
String |
用于保存Relation的名称 |
source_node |
Number |
源Node的ID |
target_node |
Number |
目标Node的ID |
两个通过Relation连接的Node中的数据可以建立连接,将所有数据的连接信息保存在名称为graphic_db_relation_record_def的DataSet中,该DataSet的数据结构如下:
执行以下步骤:
1)客户端程序调用图形数据的API,进行事务的提交操作,调用API时,传入将要提交的事务编号tx_no;
2)检查事务是否存在,若不存在则退出,否则继续下面的步骤;
3)检查事务是否已过期,若过期则退出,否则继续下面的步骤;
4)检查事务是否已提交,若提交则退出,否则继续下面的步骤;
5)检查事务是否已回滚,若回滚则退出,否则继续下面的步骤;
6)检查事务是否已被锁定,若被锁定则退出,否则继续下面的步骤;
7)标记事务回滚状态;
8)恢复事务锁定的数据记录;
9)删除脏数据;
10)删除事务记录,至此完成事务的回滚操作。
进一步地:
在所述步骤2)中,检查事务是否存在的方法是:读取名为graphic_db_tx_def的DataSet,查找tx_no列的值与API中传入的tx_no值相等的记录,如果记录存在,则意味着当前的图形数据库中存在该联机事务。
在所述步骤3)中,检查事务是否已过期的方法是:读取名为graphic_db_tx_def的DataSet,查找tx_no列的值与API中传入的tx_no值相等的记录,检查该记录中is_timeout列的值,如果值为-1,则意味着在当前的图形数据库中该联机事务没有过期。
在所述步骤4)中,检查事务是否已提交的方法是:读取名为graphic_db_tx_def的DataSet,查找tx_no列的值与API中传入的tx_no值相等的记录,检查该记录中is_commit列的值,如果值为-1,则意味着在当前的图形数据库中该联机事务没有进行提交。
在所述步骤5)中,检查事务是否已标记回滚的方法是:查找tx_no列的值与API中传入的tx_no值相等的记录,检查该记录中is_rollback列的值,如果值为-1,则意味着在当前的图形数据库中该联机事务没有回滚。
在所述步骤6)中,检查事务是否被锁定的方法是:读取名为graphic_db_tx_def的DataSet,查找tx_no列的值与API中传入的tx_no值相等的记录,检查该记录中processing列的值,如果值为-1,则意味着在当前的图形数据库中该事务没有被标记锁定。
在所述步骤7)中,标记事务回滚状态的方法是:查询graphic_db_tx_def,查找tx_no列的值与API中传入的tx_no值相等的记录,将该条记录is_rollback列的值置为1。
在所述步骤8)中,恢复事务锁定的数据记录的方法是:查询graphic_db_tx_def,查找tx_no列的值与API中传入的tx_no值相等的记录,读取该条记录的associate_node列中的记录,获取当前事务操作中相关联的节点名称,然后依次查找各关联节点数据中_tx_no列的值与当前事务记录tx_no列中值相等,且_dirty列值为-1的数据记录,将这些记录的_tx_no列的值设为null;查询graphic_db_relation_record_def,查找数据中_tx_no列的值与API中传入的tx_no值相等,且_dirty列值为-1的记录,将这些记录的_tx_no列的值设为null。
在所述步骤9)中,删除脏数据的方法是:查询graphic_db_tx_def,查找tx_no列的值与API中传入的tx_no值相等的记录,读取该条记录的associate_node列中的记录,获取当前事务操作中相关联的节点名称,然后依次查找各关联节点数据中_tx_no列的值与API中传入的tx_no值相等,且_dirty列值为1的数据记录,将这些记录从DataSet中物理删除;查询graphic_db_relation_record_def,查找数据中_tx_no列的值与API中传入的tx_no值相等,且_dirty列值为-1的记录,将这些记录从DataSet中物理删除。
在所述步骤10)中,删除事务记录的方法是:查询名称为graphic_db_tx_def的DataSet中,查找tx_no列的值与API中传入的tx_no值相等的记录,将该条记录删除。
本发明具有以下优点:
1.提供了一种简单、可靠的数据回滚机制,回滚操作具有不可分割的“原子操作”特性,在回滚与未回滚状态之间,不会出现第三种状态。
2.本发明的数据操作具有任意断点持续性,事务回滚操作调用后,在数据恢复开始至完成的任意时间点的意外执行中断,均可在再次启动系统后继续执行,直至恢复完成。
具体实施方式
本发明提出了一种图形数据库联机事务中事务回滚机制的实现方法,下面结合附图详细说明。
图形数据库概述
本发明图形数据库的架构自上而下可以分为三层。如图1所示,最上层为图形数据中各种概念对象的组织与实现。中间层为抽象的数据物理存储接口层,将物理存储的数据抽象为若干个数据集DataSet。底层为物理存储实现层,由程序借助现有的存储引擎实现,比如:传统的关系数据库,XML文件等等。
DataSet(数据集)
DataSet是图形数据库中数据的逻辑存储单元,图形数据库中的数据以及数据库自身的逻辑定义均存储在DataSet中,DataSet是一个抽象的接口,真实的数据可以通过遵循DataSet接口的实现程序存储在关系数据库、XML或自定义格式的文件中。每一个DataSet由一个全局唯一的名称和若干个列(Column)组成。DataSet中的列表支持如下两种数据类型:
类型 |
说明 |
String |
用于保存文本性的描述信息 |
Number |
用于保存整数、浮点数等数字信息,或用来保存布尔值信息,用1表示true,用-1表示false. |
表1
Node(节点)
Node为图形数据库中存储数据的逻辑单元,在图形数据库中,每一种记录实体均可抽象为Node,比如在表述一个计算机网络应用系统时,交换机中的端口、PC服务器的网卡、CPU、生产配件的厂商、我们为之提供服务的客户、系统中的用户、权限等等,每个Node拥有一个全局唯一的名称,和一些其特有的属性,用于记录配置信息,例如:相对于我们服务的客户,我们将其命名为Customer,其拥有如下属性:contractedAmount(合同总额)、industry(所属行业)、name(客户名称)、description(描述)等。在本发明中,Node的属性可以是如下类型的数据。
表2
每一个Node的定义信息均保存在名称为graphic_db_node_def的DataSet中,该DataSet的数据结构如下:
列名称 |
数据类型 |
说明 |
node_id |
Number |
全局唯一的ID |
name |
String |
用于保存Node的名称 |
表3
每一个Node中所定义的属性信息保存在名称为graphic_db_node_attr_def的DataSet中,该DataSet的数据结构如下:
表4
针对于Node的定义,物理存储的DataSet类似如下两个表:
表5
表6
每一个Node的数据信息保存在与其同名的DataSet中,假设我们有一个名称为Customer的Node,该Node有如下属性:
属性名称 |
数据类型 |
说明 |
RID |
String |
数据库内置 |
name |
String |
客户名称 |
contractedAmount |
Number |
合同金额 |
industry |
Reference |
所属行业 |
description |
String |
客户描述信息 |
表7
则该Node对应的DataSet结构为:
表8
物理存储的DataSet类似下表:
表9
RID(记录ID,Record ID)
在图形数据库中,每一个Node都会有一个名称为RID的属性,存储在Node中的每一条数据的RID值均是全局唯一的,作为该条记录在图形数据库中的标识。RID的数据类型为String型。每一个Node均含有该属性。RID格式为:Node名称+下划线+递增数字,一个典型的RID数值类似于如下形式:Industry_109。
Relation(关系)
每一类信息的实体均可以抽象为Node,在现实应用中,常常需要将这些Node按某种逻辑组织起来,Relation就是用来描述Node与Node之间的组织关系的。假设现在已有代表客户的Node:Customer,代表系统用户的Node:SysUser,在现实世界中,我们的一个销售人员会成为系统中的一个用户,并负责一些客户的销售、及沟通工作。因此,我们可以在SysUser与Customer之间建立一个名为SysUserServeCustomer的Relation来表述两者之间的关系。我们用图2来表述这种关系,Relation就是用于描述Node与Node之间关系的特殊对象。每一个Relation均有一个全局唯一的名称,一个源Node,一个目标Node。由源Node到目标Node的方向,我们称之为正向,由目标Node到起始Node的方向我们称之为反向。
每一个Relation的定义信息均保存在名称为graphic_db_relation_def的DataSet中,该DataSet的数据结构如下:
列名称 |
数据类型 |
说明 |
relation_id |
Number |
全局唯一的ID |
name |
String |
用于保存Relation的名称 |
source_node |
Number |
源Node的ID |
target_node |
Number |
目标Node的ID |
表10
针对于Relation的定义,物理存储的DataSet类似下表:
表11
按照Relation的定义,两个通过Relation连接的Node中的数据可以建立连接。所有数据的连接信息保存在名称为graphic_db_relation_record_def的DataSet中,该DataSet的数据结构如下:
表12
在应用场景中,其物理存储的DataSet类似下表:
表13
Reference(引用)
在图形数据库抽象中,一些常用的Node会与其他大部分Node有关系,这些常用的Node数据量很有限、且基本不会发生变化,比如:国家、省、市等。如果采用Relation的方式来表述的话,则需要与其他Node之间建立的大量关系,这对后期的维护将会造成一定的困难。在此种情形下,可以考虑采用Reference的形式来表述关系。一个Node通过其所拥有的属性引用另外一个Node,在其实现形式上,很大程度与RDBMS(关系数据库)的Foreign Key(外键)相类似。某一条记录的Dictionary属性中保存的是另外一个Node中数据记录的RID。考虑之前我们讨论过的Node——Customer,拥有(industry)行业这一属性,假设在我们的应用场景中,行业的数量很有限,且不会经常发生变化。则可以用Reference属性的方式引用Industry这一Node中的某条记录。数据在DataSet中的存储方式如图3所示。
在本发明中我们用虚线表示Node之间的Reference,以区别于Relation,见图4。
联机事务与非联机事务
图形数据库中数据的操作可分为:“联机事务数据操作”与“非联机事务数据操作”。联机事务数据操作步骤依次为:创建联机事务、进行联机事务数据操作(在一个联机事务中该操作可以重复多次)、提交联机事务使操作生效或者回滚联机事务放弃操作。见图5所示。而非联机事务数据操作不受事务控制,直接调用图形数据库API即可,见图6所示。
如图7所示,本发明的联机事务处理自上而下分为三层:
最上层为暴露给外部调用程序的API。
中间层为事务逻辑控制层,按操作类别分为同步区与非同步区,同步区意味着在同一时间只能有一个操作进行,其他操作在进入同步区之间均处于等待状态,该机制利用Java语言的线程同步锁定特性实现。非同步区的操作则不受限制,在任何时间均可以进行。
最下层为存储数据的DataSet操作抽象层,在DataSet中,保存有联机事务自身的状态信息,以及数据的事务状态属性信息。
在图形数据库中,联机事务的状态数据存储在名称为graphic_db_tx_def的DataSet中,该DataSet的数据结构如下:
表14
在图形数据库中每一个Node均有一个相对应的同名的DataSet,数据之间的Relation信息保存在名称为graphic_db_relation_record_def的DataSet中。这些DataSet中均缺省内置如下两个列:
表15
事务回滚机制的设计及实现
事务回滚机制的流程如图7:
(1)客户端程序调用图形数据的API,进行事务的提交操作,调用API时,传入如下参数:
tx_no:将要提交的事务编号。
在接下来的步骤中,为方便阐述,我们假定传入的tx_no参数值为123abc
(2)检查事务是否存在。读取名为graphic_db_tx_def的DataSet,查找tx_no列的值为123abc的记录,如果记录存在,则意味着当前的图形数据库中存在编号123abc联机事务,继续执行接下来的逻辑,否则,直接退出。
(3)检查事务是否已过期。读取名为graphic_db_tx_def的DataSet,查找tx_no列的值为123abc的记录,检查记录中is_timeout列的值,如果值为-1,则意味着在当前的图形数据库中编号123abc联机事务没有过期,继续执行接下来的逻辑,否则,直接退出。
(4)检查事务是否已提交。读取名为graphic_db_tx_def的DataSet,查找tx_no列的值为123abc的记录,检查记录中is_commit列的值,如果值为-1,则意味着在当前的图形数据库中编号123abc联机事务尚没有进行提交,继续执行接下来的逻辑,否则,直接退出。
(5)检查事务是否已回滚。读取名为graphic_db_tx_def的DataSet,查找tx_no列的值为123abc的记录,检查记录中is_rollback列的值,如果值为-1,则意味着在当前的图形数据库中编号123abc联机事务没有回滚,继续执行接下来的逻辑,否则,直接退出。
(6)检查事务是否已被锁定。读取名为graphic_db_tx_def的DataSet,查找tx_no列的值为123abc的记录,检查记录中processing列的值,如果值为-1,则意味着在当前的图形数据库中编号123abc联机事务没有进行数据处理,可以继续执行接下来的逻辑,否则,直接退出。
(7)标记事务回滚状态。查询graphic_db_tx_def,查找tx_no列的值为123abc的记录,将该条记录is_rollback列的值置为1,如下所示:
表16
(8)恢复事务锁定的数据记录。
a.查询graphic_db_tx_def,查找tx_no列的值为123abc的记录。读取该条记录的associate_node列中的记录,获取当前事务操作中相关联的节点名称,然后依次查找各关联节点数据中_tx_no列的值为123abc,且_dirty列值为-1的数据记录。将这些记录的_tx_no列的值设为null。
b.查询graphic_db_relation_record_def,查找数据中_tx_no列的值为123abc,且_dirty列值为-1的记录。将这些记录的_tx_no列的值设为null。
(9)删除脏数据。
a.查询graphic_db_tx_def,查找tx_no列的值为123abc的记录。读取该条记录的associate_node列中的记录,获取当前事务操作中相关联的节点名称,然后依次查找各关联节点数据中_tx_no列的值为123abc,且_dirty列值为1的数据记录。将这些记录从DataSet中物理删除。
b.查询graphic_db_relation_record_def,查找数据中_tx_no列的值为123abc,且_dirty列值为-1的记录。将这些记录从DataSet中物理删除。
(10)删除事务记录。查询名称为graphic_db_tx_def的DataSet中,查找tx_no列的值为123abc的记录,将该条记录删除。完成事务的回滚操作。