移动实时环境下的数据一致性研究
2011-02-07王小荣
帖 军,王小荣,金 佳
(中南民族大学计算机科学学院,武汉430074)
随着互联网的不断延伸和无线接入技术的快速发展,人们希望能在任意时间、地点访问任意数据并且对突发数据做出及时反应的需求已逐渐成为现实,信息系统正在走出传统的机房与桌面,帮助用户随时随地获取相关信息,做出正确决策.因此,一种新的移动实时数据库系统应运而生并迅速发展起来.这种新的数据库技术主要用于维护数据的一致性,支持多用户的并发访问,使用户可以随时随地查询和更新数据库.
在移动实时计算环境中,虽然同样可以满足事务的ACID[1]特性,保持系统的严格一致性,但是这样会造成许多事务的回滚操作[2],使得系统频繁地处于抖动状态,严重影响移动用户的使用,所以我们经常会引入一些其他的规则(如:隔离级别),在不同的情况下采用不同的隔离级别,以牺牲一定的数据准确性来提高数据的处理效率,即提高事务的并发性.
由于目前国内外对基于悲观并发控制的事务处理技术已经很成熟,所以本文基于悲观并发控制对数据的不一致性进行分析,并找到一种新的隔离级别划分的方法来实现事务的并发执行.
1 传统隔离级别
1.1 相关概念
本文在分析数据不一致性时,将事务划分为本地事务和内存事务.我们基于锁控制方案提出保持数据一致性的相关策略.首先引入几个相关概念.
定义1本地事务:在单个数据库中并且限制在单个进程内的操作序列,该序列由读操作或写操作组成并以提交或中止操作结束.
定义2内存事务:对存放于主存中的数据集进行操作的序列,该序列由读操作或写操作组成并以提交或中止操作结束.
定义3读长锁:若事务T对数据D加读长锁,则其他事务也只能对其加读锁,不能加写锁,而且在整个事务范围内,该锁都有效,直到该事务以提交或回滚完成,才允许其他事务对D进行写操作.
定义4读短锁:若事务T对数据D加读短锁,则在T读取D时,只允许其他事务对D加读锁,不能加写锁,一旦读取数据结束,该锁就立即被释放,此时才允许写锁发生.
定义5写长锁:若事务T对数据D加写长锁,则在T更改D时,不允许其他事务对D做任何操作,而且在整个事务范围内,该锁都有效,直到事务T以提交或回滚完成,才允许其他事务操作D.
1.2 传统隔离级别
传统隔离是通过实行不同锁机制来实现的[3],如:何时加锁,加何种类型锁,加多长时间锁等.传统的4个隔离级别都是通过对写操作加长锁,其不同在于,对于读锁,锁的持有期是不一样的.
这4个隔离级别解释如下:
(1)read_uncommitted未提交读,事务对读操作不加任何锁,对写操作加写长锁.
(2)read_committed已提交读,事务对读操作读短锁,对写操作加写长锁.
(3)repeatable_read可重复读,事务只对读取的数据项加读长锁和写长锁.
(4)serializable串行化,事务对所有的数据表上都加读长锁和写长锁.
这些隔离级别都是通过封锁规则定义的,我们可以设计出并发控制算法来实现这些隔离级别,以此来使移动实时数据库中的数据保持一致.表1为传统隔离级别下的数据不一致[4],Y表示3种不一致现象在各隔离级别中存在,N表示不存在.
表1 传统隔离级别下的数据不一致Tab.1 Data inconsistency at traditional isolation levels
通过表1我们发现只有在严格的锁控制方案中,即:2级和3级隔离级别,才能保持数据不发生写丢失、脏读和不可重复读这些数据不一致[5],但是这样做会使得并发度严重下降,接下来我们将具体分析这3种数据不一致性.
2 数据的不一致性分析
本文讨论的数据不一致问题主要是指在数据事务处理过程中,由于并发控制机制不合理而导致事务间的并行执行结果有误的现象.本文将事务划分为2种事务,即内存事务和本地事务,根据数据不一致对事务执行的准确性的影响程度,依次分析写丢失、脏读、不可重复读这3种不一致性.
2.1 写丢失
(1)形式化定义.
事务ti,tj∈T,i≠j,ri(x),wi(x) ∈ti,rj(x),wj(x)∈tj.
1)若ti,tj为内存事务,存在s=ri(x)wi(x)·rj(x)wj(x)ai或s=ri(x)rj(x)wj(x)wi(x)ai/ci;
2)若ti,tj为本地事务,存在s=ri(x)wi(x)·rj(x)wj(x)ci cj或s=ri(x)rj(x)wj(x)wi(x)ai/ci.则称该并发执行的事务调度发生了写丢失.
(2)意义.
两个事务接连修改了同一个数据项x的值,使得一个事务修改的值将另一个事务的值覆盖掉,或两个事务同时对一个数据项进行修改,则由于一个事务的回滚使得另一事务修改的值也不得不丢失,这两种情况都称为写丢失(或丢失更新).
(3)典型事例分析及对策.
1)内存事务序列.
①s=r1(x)w1(x)r2(x)w2(x)a1.
内存事务2读取内存事务1写x的值,但由于内存事务1的回滚使得内存事务2发生写丢失.
解决方法:写长锁、读短锁.使得序列s=rl1(x)r1(x)w1(x)wu1(x)a1rl2(x)r2(x)w2(x)wu2(x).
②s=r1(x)r2(x)w2(x)w1(x)a1.
内存事务2由于内存事务1的写操作的回滚而造成写丢失.
解决方法:写长锁、读长锁.使得序列s=rl1(x)r1(x)rl2(x)r2(x)w2(x)wu2(x)a2w1(x)wu1(x)a1.
③s=r1(x)r2(x)w2(x)w1(x)c1.
内存事务2由于内存事务1的写提交操作将自身写的数据给覆盖掉.
解决方法:写长锁、读长锁.使得序列s=rl1(x)r1(x)rl2(x)r2(x)w2(x)wu2(x)a2w1(x)wu1(x)c1.
2)本地事务序列.
①s=r1(x)w1(x)r2(x)w2(x)c2a1.
事务2由于事务1的回滚而造成写丢失.
解决方法:写长锁、读短锁.使得序列s=rl1(x)r1(x)w1(x)wu1(x)a1rl2(x)r2(x)w2(x)wu2(x)c2.
②s=r1(x)w1(x)r2(x)w2(x)c2c1.
事务2由于事务1的后提交,其值被事务1的值覆盖掉.
解决方法:写长锁、读短锁.使得序列s=rl1(x)r1(x)w1(x)wu1(x)c1rl2(x)r2(x)w2(x)wu2(x)c2.
③s=r1(x)r2(x)w2(x)w1(x)c1c2.
事务1由于事务2的后提交,其值被覆盖掉.
解决方法:写长锁、读长锁.使得序列s=rl1(x)r1(x)rl2(x)r2(x)w2(x)wu2(x)a2w1(x)wu1(x)c1.
2.2 脏读
(1)形式化定义.
事务ti,tj∈T,i≠j,ri(x),wi(x) ∈ti,rj(x),wj(x)∈tj,若存在以下情况之一,
1)ti,tj为本地事务,存在s=wi(x)rj(x)ci;
2)ti,tj为内存事务,存在s=wi(x)rj(x)ai或s=rj(x)wi(x)ci,则称tj读脏数据x.
(2)意义.
当一个事务正在访问数据,并且对该数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问这个数据,然后使用了这个数据,进而造成的数据库不一致.
(3)典型事例分析及对策.
1)内存事务序列.
①s=r1(x)w1(x)r2(x)a1.
内存事务2由于内存事务1的回滚,其读取的x与数据库中的x值不一致.
解决方法:写长锁、读短锁.使得序列s=rl1(x)r1(x)w1(x)wu1(x)a1rl2(x)r2(x)ru2(x).
②s=r1(x)r2(x)w1(x)c1c2.
内存事务2由于读取x的值早于内存事务1更改x的值,当内存事务1提交时,内存事务2已读取x的值与数据库中x值不一致.
解决方法:写长锁、读长锁.使得序列s=rl1(x)r1(x)rl2(x)r2(x)w2(x)wu2(x)a2w1(x)wu1(x)c1.
2)本地事务序列.
事务2在事务1更改x值前读取x,当事务1提交时,其已读取的x与数据库中被更改的x值不一致.
解决方法:读长锁、写长锁.使得序列s=rl1(x)r1(x)rl2(x)r2(x)w2(x)wu2(x)a2w1(x)wu1(x)c1.
2.3 不可重复读
(1)形式化定义.
事务ti,tj∈T,i≠j,ri(x),wi(x) ∈ti,rj(x),wj(x)∈tj.
1)若ti,tj为本地事务,存在s=ri(x)rj(x)·wj(x)cj ri(x),则ti不可重复读数据项x.
2)若ti,tj为内存事务,存在s=ri(x)rj(x)·wj(x)ri(x),则ti不可重复读数据项x.
(2)意义.
在一个事务内,多次读同一数据,在这个事务还没有结束时,另外一个事务也访问该数据.那么,在第1个事务的两次读数据之间,由于第2个事务的修改,那么第1个事务两次读到的数据可能是不一样的.这样就发生了一个事务内两次读到的数据是不一样的,称为这个事务不可重复读该数据项.
(3)典型事例分析及对策.
1)内存事务序列.
s=r1(x)r2(x)w2(x)r1(x).
内存事务1前后两次读取x之间由于内存事务2对x直接更改使得前后在数据库中读取的x值不一致.
解决方法:写长锁、读长锁.使得序列s=rl1(x)r1(x)rl2(x)r2(x)w2(x)wu2(x)a2r1(x).
2)本地事务序列.
s=r1(x)r2(x)w2(x)c2r1(x).
事务1前后两次读取x之间由于事务2对x更改并提交数据库使得前后在数据库中读取的x值不一致.
解决方法:写长锁、读长锁.使得序列s=rl1(x)r1(x)rl2(x)r2(x)w2(x)wu2(x)a2r1(x).
表2为将事务划分为本地事务和内存事务时,在不同隔离级别下存在的数据不一致性的总结,表2中数据含义同表1.
表2 不同隔离级别下的数据不一致性Tab.2 Data inconsistency at different isolation levels
3 新的隔离方法
我们发现传统隔离级别中隔离级的高低与事务的并发度是矛盾的.维护一个最高的隔离级别虽然会防止数据的出错,但是却导致了并行度的损失,以及增加死锁出现的可能性,而降低隔离级别,又会引起一些难以发现的问题.所以对数据库使用何种隔离级别要慎重.并且在上文对数据不一致性的分析中我们也发现在1级隔离级别的情况下还是会有脏读情况发生,而在0级隔离情况下也会有不发生脏读的情况,这样单一的使用隔离级别的话就会降低某些事务的执行效率,甚至导致事务执行时产生冲突,从而导致数据的不一致.
对此,我们可以采用一种新的划分事务隔离级别的方法,当事务的调度序列中出现形如wi(x)rj(x)这样的序列,那么我们就采用在写操作上加写长锁,而对于读操作就只需加读短锁.当事务的调度序列中出现形如rj(x)wi(x)这样的序列,那么我们就要对其读操作加读长锁,写操作加写长锁.这么做既简单,还能防止数据的不一致(如表3所示,表3中数据含义同表1).
表3 解决数据不一致性的新方法Tab.3 New solution of data inconsistency
4 结语
在移动实时数据库的并发控制中,除了要保证数据的一致性外,还需要考虑事务处理的效率问题,如:在提高数据一致性的基础上提高事务的并发度、有限资源的利用率、系统效率等.本文提出的方法既可以保证事务的数据一致性,又提高了事务的并发度,且该方法简单、易于实现.但是,对于某些含有rj(x)wi(x)的调度序列的事务的并发执行中,该方法有时还是会与传统隔离级别一样,产生锁过于严格的缺点.而对于如何解决这个问题,需要做进一步的研究.
[1]Ghorbanzadeh P,Shaddeli A,Malekzadeh R,et al.A survey of mobile database security threats and solutions for it[J].Information Sciences and Interaction Science(ICIS),2010(6):676-682.
[2]Yadav D S,Agrwal R,Saraswat R C.Analysis of cooperation processing with full and partial aborts in active database[J].Information,Communications and Signal Processing,2003(12):1670-1674.
[3]Lu Shiyong,Bernstein A,Lewis P.Correct execution of transactions at different isolation levels[J].Knowledge and Data Engineering,2004(9):1070-1081.
[4]Rahman S,Shrestha GB.Analysis of inconsistent data in power planning[J].Power Systems,1991(1):225-230.
[5]Zhen Chenggang,Li Kai.Memory management research based on real-time database[J].International Conference on Test and Measurement,2009(1):416-419.