暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

第 5 章:事务引擎 5.7 锁

145

5.7 锁

锁是一种解决数据库并发问题的一种设计。

如果一昧的加一种锁,比如全局锁,只要有事务来访问数据,就会申请一个全局锁,虽然从理论上来说,这样是可行的,但毫无疑问,这样的并发管理能力太差,所以需要一些更细粒度化的锁来进行并发控制。


细粒度的锁

将锁更细粒度化可以分为共享锁(share-mode lock;S-lock)和独占锁(exclusive-mode lock;X-lock),也就是读锁和写锁,事务进行读取的时候,获取数据的读锁,其他事务要修改必须要等待解锁。如果事务进行更新操作的时候,需要获取数据的写锁,只有该事务能对该数据进行读写操作。

只有读锁之间可以相互兼容,其他情况都是不兼容。

S-lockX-lock
S-lock兼容不兼容
X-lock不兼容不兼容

这里通过一个简单的示例来帮助大家理解。

T1:B 转账给 A 50 元

T2:读一下 A 和 B 的余额之和

img

第一眼看上去感觉结果是合理,假设 A 和 B 原来都只有 100 元,事务 T2 无论在 T1 执行前还是执行后进行操作,读取的结果都是 200 元。

img

这样 T2 在 T1 中间执行,锁之间的使用是合理的,这种情况下 T2 的结果就会是 150 元。

那怎么处理才能解决上面这种情况呢,很容易想到的就是事务在最后的时刻释放读写锁,这样看上去也很合理,但会出现下面这种情况:

img

这种情况下,T3 占着 B 的写锁,T4 占着 A 的读锁,这个时候 T3 去申请 A 的写锁,T4 申请 B 的读锁,很明显,这种情况下死锁了。

因此为了避免这种情况,我们引入了两阶段加锁,在获取锁的阶段(growing phase),事务只能不断地获取新锁,在释放锁(shrinking phase)阶段,事务只能不断的释放锁。


两阶段加锁

img

但同样也会遇到上述的情况,在 T5 遇到错误的时候,会导致 T6 和 T7 的连锁回滚。为了避免连锁回滚,我们引入更严格的两阶段加锁,写锁必须等事务结束后释放,这样就避免在事务未提交的时候,其他事务不会来进行数据改写,因此避免了连锁回滚。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论