13 | 隔离性:为什么使用乐观协议的分布式数据库越来越少?
王磊
该思维导图由 AI 生成,仅供参考
你好,我是王磊,你也可以叫我 Ivan。
我们在 11、12 两讲已经深入分析了读写冲突时的控制技术,这项技术的核心是在实现目标隔离级别的基础上,最大程度地提升读写并发能力。但是,读写冲突只是事务冲突的部分情况,更多时候我们要面对的是写写冲突,甚至后者还要更重要些。
你可能经常会听到这类说法,“某某网站的架构非常牛,能抗住海量并发”“某某网站很弱,搞个促销,让大家去抢红包,结果活动刚开始 2 分钟系统就挂了”。其实,要想让系统支持海量并发,很重要的基础就是数据库的并发处理能力,而这里面最重要的就是对写写冲突的并发控制。因为并发控制如此重要,所以很多经典教材都会花费大量篇幅来探讨这个问题,进而系统性地介绍并发控制技术。在这个技术体系中,虽然有多种不同的划分方式,但最为大家熟知就是悲观协议和乐观协议两大类。
TiDB 和 CockroachDB 的流行一度让大家对于乐观协议这个概念印象深刻。但是,经过几年的实践,两款产品都将默认的并发控制机制改回了悲观协议。他们为什么做了这个改变呢?我们这一讲,专门来探讨什么是乐观控制协议,以及为什么 TiDB 和 CockroachDB 不再把它作为默认选项。
并发控制技术的分类
首先,无论是学术界还是工业界,都倾向于将并发控制分为是悲观协议和乐观协议两大类。但是,这个界限在哪,其实各有各的解释。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
分布式数据库的并发控制技术一直备受关注,其中悲观协议和乐观协议是两大主流分类。本文深入探讨了乐观协议的实现方式以及为何一些分布式数据库产品不再将其作为默认选项。乐观协议的核心是在事务提交时检查是否满足隔离级别,如果满足则提交,否则回滚并自动重新执行。TiDB作为一个广义上的乐观并发控制系统,虽然对每个修改行做了有效性验证,但从整体看并未做全局有效性验证,因此仍相对乐观。此外,文章还介绍了狭义乐观并发控制(OCC)的具体定义和应用情况。通过对乐观协议的深入探讨,读者能够更好地理解分布式数据库的并发控制技术及其在实际应用中的特点。 文章还探讨了乐观协议的挑战,包括事务频繁冲突和遗留应用的兼容性需求。由于这些挑战,TiDB的并发控制机制也做出了改变,增加了“悲观锁”并作为默认选项。悲观锁的引入使TiDB转变为一个可交互事务模式,出现死锁的概率大幅提升,对应增加死锁检测功能。 总的来说,本文深入探讨了乐观协议和悲观协议在分布式数据库中的应用和挑战,以及TiDB在面对这些挑战时所做的改变。这对读者更好地理解分布式数据库的并发控制技术及其在实际应用中的特点具有重要意义。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《分布式数据库 30 讲》,新⼈⾸单¥59
《分布式数据库 30 讲》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(5)
- 最新
- 精选
- 扩散性百万咸面包老师感觉这里没说清楚: TiDB在2PC prewrite阶段会给每一行加锁,这个锁是局部性的,怎么理解局部性?意思是说这个加锁只是这个事务的单方面行为,而没有通过数据库的锁管理器等组件吗?因为我看到TiDB是会观察所有加锁请求是否成功的,感觉这好像已经算是做全局性的有效验证了?要怎样加锁才是全局性的有效验证呢?
作者回复: 局部性是说,只要局部加锁成功,就开始局部的写入了。TiDB的乐观锁也不是在所有记录加锁成功以后,才写入新的数据版本。如果是,那还会因为事务冲突多而频繁回滚吗?再想想:) 怎么加锁才是全局有效性验证?TiDB后来增加的悲观锁就是例子。这个加锁动作是统一的,只要有一条记录加锁不成功,就不会启动任何写入动作。
2020-09-1011 - 春风老师,TiDB全局性验证是否是增加了一轮共识算法的时间
作者回复: 是的,因为TiDB的悲观锁是要写一个实际的占位符,并且必须成功后,才能开始原有的乐观锁处理过程,所以就会增加一轮共识算法时间。
2020-09-075 - 扩散性百万咸面包一个非常典型的例子就是 select for update。这是一个显式的加锁操作,或者说是显式的方式进行有效性确认,广义的乐观协议都不提供严格的 RVW,所以也就无法支持这个操作。 这句话没懂,广义的乐观协议不是支持加锁吗(比如TiDB对每一行修改前加锁)?还是说像TiDB这样的,它的加锁不是显式的,只能在percolator 2PC中加锁,所以不支持这种显式加锁的。2020-09-0712
- Peter Yu乐观协议(RVW)和悲观协议(VRW)是不是分别理解为DVC(do、validate、commit)和VDC(validate、do、commit)更合适。因为这里的R太让人费解,也容易误解 对于乐观协议,因为多数情况只要执行业务逻辑(do),然后直接提交(commit)即可,虽然涉及validate,因为没有冲突,所以没有rollback,所以validate的损耗可以忽略。 对于悲观协议,先要validate,已发现冲突就加锁,其他事务进不来。本事务完成业务逻辑(do)和提交(commit)后再释放锁。 更白话一点: 乐观协议就是管你会不会冲突,我直接开干,遇到冲突再说,冲突了就回滚。虽然回滚的成本高,但是总体回滚的次数不多,综合来看这部分损耗忽略不计。 悲观协议就是我预计只要一开干就很可能会资源冲突,用乐观协议的做事方式来,会有不计其数的回滚,此时还不如排队一个个来做。当做的时候,先获取锁,获取到,干完活,在提交成果物,最后释放锁。 不知这样理解可不可以,忘老师指教2022-06-22
- 真名不叫黄金老师,你好,有一个问题想请教一下: Spanner 在文档中称自己的事务是基于悲观锁的,但是其实它也是将 Writes 缓存住的,在 commit 时一次性获取锁、完成两阶段提交,它在执行 DML 时并没有检测冲突,Spanner 在提交时采用伤停等待策略,实践中确实可能会带来冲突时很多事务的大量 abort 和 retry。 按照老师文中的标准,Spanner 其实是一种乐观事务对吗?2020-09-09
收起评论