事务并发控制

一、四类并发问题及四种事务隔离级别

首先介绍四类并发问题:

1.更新丢失:两个事务都同时更新一行数据,一个事务对数据的更新把另一个事务对数据的更新覆盖了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。

2.脏读:一个事务读到另一个事务未提交的更新数据(A和B事务并发执行,B事务执行更新后,A事务查询B事务没有提交的数据,B事务回滚,则A事务得到的数据不是数据库中的真实数据。也就是脏数据,即和数据库中不一致的数据)。

3.不可重复读:一个事务读到另一个事务已提交的更新数据(A和B事务并发执行,A事务查询数据,然后B事务更新该数据,A再次查询该数据时,发现该数据变化了)。

4.幻读:一个事务读到另一个事务已提交的新插入的数据(A和B事务并发执行,A事务查询数据,B事务插入或者删除数据,A事务再次查询发现结果集中有以前没有的数据或者以前有的数据消失了)。

相应的有四种事务隔离级别供用户选用:

更新丢失脏读不可重复读幻读
未提交读NYYY
已读提交NNYY
可重复读NNNY
串行化NNNN

二、两阶段封锁协议(2PL)及解决死锁的方法

下面介绍两阶段封锁协议(2PL)。2PL可以使事务的隔离级别达到可串行化。
2PL要求每个事务分两个阶段提出加锁和解锁申请:

1.增长阶段:事务可以获得锁,但是不能释放锁
2.缩减阶段:事务可以释放锁,但是不能获得锁

一开始,事务处于增长阶段,事务根据需要获得锁。一旦该事务释放锁,就进入缩减阶段,不能再发出加锁请求。我们可以证明2PL协议保证冲突可串行化。对于任何事务,在调度中该事务获得其最后的加锁位置(增长阶段结束点)称为事务的封锁点。这样,多个事务可以根据它们的封锁点进行排序,实际上,这个顺序就是事务的一个可串行化顺序。
但是,2PL不保证不发生死锁,例如:

T3T4
lock-X(B)
read(B)
B:=B-50
write(B)
lock-S(A)
read(A)
lock-S(B)
lock-X(A)

*其中lock-X表示排它锁,lock-S表示共享锁

此时,事务T3等待T4释放A上的共享锁,T4等待T3释放B上的排他锁,发生死锁。
死锁的解决方法有两种,一种是预防,一种是检测与恢复。这里采用第二种方法,锁的等待关系可以用有向图来表示,如T3->T4表示T3等待T4释放锁。转化为图后,如果有向图中有环,则有死锁。这里使用NyaDB的死锁检测与恢复方法:

1.设置一个时间戳stamp = 0;
2.为每个点设置一个”访问戳”, visStamp, 初始化为-1;
3.任意选择一个visStamp为-1的点, 设它为s;
4.stamp++;
5.从s开始遍历, 对每个遍历到的点u进行下面的判断:
6.===> 如果visStamp[u] == -1, 则visStamp[u] = stamp, 继续遍历;
7.===> 如果visStamp[u] != -1 and visStamp[u] < stamp, 跳过点u, 即不以它为节点继续向下遍历;
8.===> 如果visStamp[u] == stamp, 则有环, 结束算法;
9.当从s开始遍历完且并没发行环, 重复3), 直到没有visStamp为-1的点.
10.当整个算法结束时, 都没发现环, 则无环.

将等待图维护在内存中, 每当出现等待时, 则向图中加入一条边。 每向图中加入一条边, 便进行一次死锁检测。 如果加入某条边后检测到了死锁, 则撤销加入这条边的事务。

三、新的问题—级联回滚

考虑如下图的事务调度:

T5T6T7
lock-X(A)
read(A)
lock-S(B)
read(B)
write(A)
unlock(A)
lock-X(A)
read(A)
write(A)
unlock(A)
lock-S(A)
read(A)

如果在事务T7的read(A)步骤之后事务T5发生故障需要回滚,此时虽然T6和T7并没有发生故障,但是因为这两个事务中有一部分命令是在事务T5开始到故障点之间执行的,所以也需要回滚,这就导致了级联回滚。
级联回滚需要撤销大量的工作,这是数据库系统不希望见到的。可以通过将2PL协议变为严格2PL协议来避免级联回滚。严格2PL协议不仅要求封锁是两阶段的,还要求事务持有的所有排他锁必须在事务提交之后才能释放。这个要求保证了未提交事务所写的任何数据在该事务提交之前均以排他锁方式加锁,防止了其他事务读取这些数据。

应用严格2PL协议的级联回滚事务调度变成了下图的样子,防止了级联回滚的出现:

T5T6T7
T5 begins
lock-X(A)
read(A)
lock-S(B)
read(B)
write(A)
unlock(A)
…………
release all lock
T5 is finished
T6 begins
lock-X(A)
read(A)
write(A)
unlock(A)
…………
release all lock
T6 is finished
T7 begins
lock-S(A)
read(A)
…………
release all lock
T7 is finished

参考文献:

1.NyaDB的技术文档:https://qw4990.gitbooks.io/nyadb/content/chapter4.html
2.数据库系统概念(原书第5版) 第16章 并发控制

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值