乐观机制的并发控制
来源:互联网 发布:成品app直播源码 编辑:程序博客网 时间:2024/05/01 22:44
最近在学习《On Optimistic Methods for Concurrency》这篇论文的时候对论文进行了一些整理:
论文提出的目的:
1.由于计算机的主存有限,所以无法一次将要处理的数据全部加载入内存,只有在需要使用到该数据的时候才会从辅存中将数据调入主存中。
2.主存中的数据会被多个进程访问如果不支持并发的话,使得硬件使用率降低。
在并发控制中主要采取的控制方法有两种,即悲观的与乐观的并发控制方式。
所谓悲观的控制方式即采用加锁的形式,来支持数据库的并发访问。
所谓乐观的控制方式主要分为时间戳和有效验证这两种形式。而这篇论文主要是介绍有效验证的这一种形式。
论文中认为悲观的控制方法存在以下问题:
1.维护无死锁状态成为一种系统开销
2.没有一种普遍适用的无死锁协议来支持并发访问
3.常访问节点被锁住(比如树的根节点)
4.事务自身发生错误而中止,而锁只能在事务结束后才被释放
所以提出了乐观的并发控制方法,论文的主题是:假设系统中大部分是只读事务,写事务以及其他极端情况是非常罕见的,为极端情况提出了解决方法,使得系统在大部分情况下能够良好运行,在极端情况下也能够运行。
只读事务下:由于只读事务不会对数据库的一致性产生影响,所以可以对只读事务完全不加限制。
写事务:写事务需要分为三个阶段
1 读。在第一阶段,事务从数据库中读其读集合中的所有元素。事务还在其局部地址空间中计算它将要写的所有值。
2 有效性确认。在第二阶段,调度器通过比较该事务与其他事务的读写集合来确认该事务的有效性
3 写。在第三阶段,事务往数据库中写入其写集合中元素的值。
将写事务分为如下操作:
create create a new object and return its name.
delete( n) delete object n.
read(n, i) read item i of object n and return its value.
write (n, i, u) write u as item i of object n.
COPY( n) create a new object that is a copy of object
n and return its name.
exchange(n1, n2) exchange the names of objects nl and n2.
每个操作的具体执行过程如下:
tcreate = (
n := create;
create set := create set U {IL} ;
return n)
twrite(n, i, u) = (
if n E create set
then write(n, i, u)
else if n E write set
then write( copies[ n], i, u)
else (
m := copy(n);
copies[ n] := m;
write set := write set U {n);
write (copies[n], i, u)))
tread(n, i) = (
read set := read set U {n} ;
if n E write set
then return read (copies[ n], i)
else
return read (n, i))
tdelete (n) = (
delete set := delete set U (n}).
我们可以看到以上想表达的主要思想是:将对数据产生写的事务全放到副本中进行操作,只有当事务通过验证阶段,证明可以执行后,才真正升级为全局性的,同步到数据库中。
1.当写操作成功是,执行for n E write set do exchange ( n, copies[ a]).
2.当写操作发生冲突的时候,执行(for n E delete set do delete(n);
for n E write set do delete( copies[n])).
验证阶段需要满足的3个条件:
我们假设I事务在j事务之前,也就是说I的事务号比j小,
t(i)<t(j)
(1) T(i)必须在T(j)开始读阶段前完成其写阶段
(2) Ti的写集合与Tj的读集合没有交集,并且Ti在Tj开始它的写阶段前完成其写阶段
(3) Ti的写集合与Tj的读或者写集合没有交集,并且Ti在Tj完成它的读阶段前完成其读阶段
也就是说Ti不影响Tj的读或者写阶段
那么我们该在什么时候给事务加上事务号呢?很自然我们会想到在读阶段开始之前就为事务加上事务号,但这并不是最好的选择,因为我们假设i事务比j事务先执行,那么自然的t(i)<t(j),但是如果i的读阶段非常的长,而j快速的完成了读阶段(我们说在读阶段可以不加任何限制)那么j即使完成了读阶段,也只能等待i完成验证阶段后才进行验证,这与我们提高事务的响应时间的初衷是违背的,所以我们可以在事务进行完读阶段后再为事务加上事务号,以此来解决这一问题。
那么当事务失败了该怎么办?答案是,取消事务,让事务重做。因为我们假设这样的情况是极少发生的。
那么如果重做后依然失败呢?那么事务会进入一个临界的阶段,当事务调度器发现了这个饥饿的事务后(通过每个事务的开始时间),就会通过不释放这个事务的信号量(相当于一种锁机制)来使得这个事务成功执行。
验证阶段需要维护的集合:
为了能够验证事务的有效性,调度器需要维护三个集合
create set := empty;
read set := empty;
write set := empty;
delete set := empty;
start tn := tnc)
tend = (
(finish tn := tnc;
valid := true;
for t from start tn + 1 to finish tn do
if (write set of transaction with transaction number t intersects read set)
then valid := false;
if valid
then ((write phase); tnc := tnc + 1; tn := tnc));
if valid
then ( cleanup )
else (backup)).
1.假设U事务满足:
a)U在VAL或FIN中;即U已经过有效性确认。
b)FIN(U)>START(T);即U在T开始前没有完成。
c)RS(T)与WS(U)非空,假设其包含数据库元素X。
那么U有可能在T读X后写X。事实上,U甚至可能还没开始写X。由于我们不知道T是否读到U的值,我们必须回滚以避免T和U的动作与假设串行顺序不一致的风险。
2.假设U事务满足:
a)U在UAL中;即U有效性已经成功确认
b)FIN(U)>VAL(T);即U在T进入其有效性确认阶段以前没有完成
c)T和U的写集有交集,假设交集元素为X
T和U都必须写X的值,而如果我们确认T的有效性,它就可能在U前写X,由于我们不能确定,我们回滚T以保证它不会违反假设的T在U后的串行顺序。
mid tn := tnc;
valid := true;
if (write set of transaction with transaction number t intersects read set)
then valid := false;
(finish tn := tnc;
for t from mid tn + 1 to finish tn do
if (write set of transaction with transaction number t intersects read set)
then valid := false;
if valid
then (( writephase); tnc := tnc + 1; tn := tnc));
if valid
then (cleanup)
else (backup)).
(finish tn := tnc;
finish active := (make a copy of active);
active := active U { id of this transaction } ) ;
valid := true;
if (write set of transaction with transaction number t intersects read set)
then valid := false;
for i E finish active do
if (write set of transaction Ti intersects read set or write set)
then valid := false;
if valid
then (
(write phase);
(tnc := tnc + 1;
tn := tnc;
active := active- (id of this transaction) ) ;
(cleanup))
else (
(active := active- { id of transaction} ) ;
(backup))).
- 乐观机制的并发控制
- Hibernate的乐观锁并发控制机制
- 并发控制的悲观与乐观策略
- 乐观并发控制
- 并发控制乐观锁Version
- Entity Framework 乐观并发控制
- JPA/Hibernate:基于版本的乐观锁并发控制
- hbase的并发控制机制
- hibernate之控制并发访问(乐观并发控制之外获得额外的隔离性保证)
- 数据库并发控制及SQL Server的并发控制机制
- Oracle并发控制中的乐观锁
- Hibernate并发控制乐观锁实现-Version
- Nosql Mongodb 并发控制之乐观锁
- Nosql Mongodb 并发控制之乐观锁
- 乐观锁与悲观锁(并发控制)
- hibernate之控制并发访问(乐观并发控制之外获得额外的隔离性保证--使用LockMode.UPGRADE的实例)
- Java并发的核心控制机制
- hibernate之控制并发访问(乐观并发控制之理解乐观策略)
- jQuery 遍历 - eq() 和siblings() 方法
- Java中 -1l<<<1是多少?
- OpenCV&Qt学习之一——打开图片文件并显示
- 【实验二】单链表的实验验证
- CentOS 安装xserver
- 乐观机制的并发控制
- 字符串查找问题
- 从C语言谈程序语言
- Codeforces Round #271 (Div. 2)
- 线段树(敌兵布阵)
- windows编程——窗口样式
- HDU 2203 亲和串(kmp)
- 从局部对峙,到互联网全面开火
- C#创建XML文件