业务开发算法 50 讲
黄清昊
Hashdata 数据库内核工程师,LeetCode 高赞答主,公众号微扰理论作者
23292 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
业务开发算法 50 讲
15
15
1.0x
00:00/00:00
登录|注册

28|MVCC:如何突破数据库并发读写性能瓶颈?

乐观并发控制
性能提升
可见性规则
低水位和高水位
视图数组
当前读
快照读
undo log
隐藏列
事务ID
加锁和MVCC
不加锁
加锁
幻读
不可重复读
脏读
持久性
隔离性
一致性
原子性
MVCC的性能优势是否普遍适用
RC隔离等级和MVCC
MVCC的优势
事务和隔离等级的重要性
读视图
快照读
版本链
核心概念
避免读时加锁
读已提交和可重复读
读未提交
串行化
串行化
可重复读
读已提交
读未提交
并发事务导致的问题
例子:银行转账
保证ACID特性
思考题
总结
MVCC工作机制
MVCC(Multi-Version Concurrency Control)
实现不同隔离等级
事务隔离等级
隔离性问题
事务的必要性
MVCC:如何突破数据库并发读写性能瓶颈?

该思维导图由 AI 生成,仅供参考

你好,我是微扰君。
过去两讲,我们学习了数据库中查询优化的一个重要手段——索引,通过空间换时间的思想,从数据结构查询本身的时间复杂度和 IO 开销两个角度,去提高查询的速度。除此之外,查询能做的优化其实还有很多,比如同样的语句在采用不同查询计划的情况下,查询效率可能也是差距很大的。
今天我们就从业务开发非常常见的一个角度,并发,来聊一聊数据库可能的性能优化。首先来看并发场景下,我们在数据库中会碰到什么样的问题。

为什么需要事务

我们知道,主流的关系型数据库都能做到在高并发的场景下支持事务,比如 MySQL 的 InnoDB 引擎就支持事务,从而取代了并不支持事务的 MyISAM 引擎。但为了保证事务性,其实需要付出一定的性能代价。那事务是什么,我们来简单复习一下。
简单来说,事务就是指一系列操作,这些操作要么全部执行成功并提交,要么有一个失败然后全部回滚像什么都没发生一样,绝对不会存在中间有一部分操作得以执行,一部分没有执行。
为什么数据库中需要事务呢,一个非常经典的例子就是银行转账,比如说我们需要从 A 账户给 B 账户转 200 元。整个过程要分为两个步骤,分别是:对 A 的账户余额减去 200、对 B 的账户余额加上 200,如果这两个操作一个成功一个失败,显然会导致业务数据完整性出现问题。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

MVCC(多版本并发控制)是数据库中解决并发读写性能瓶颈的重要技术。本文首先介绍了事务的概念和隔离性问题,包括脏读、不可重复读和幻读。随后讨论了四种不同的事务隔离等级:读未提交、读已提交、可重复读和串行化,并解释了它们的实现方式和特点。最后,文章重点介绍了MVCC机制在InnoDB引擎中的应用,以实现数据库的可重复读隔离等级。通过MVCC,数据库能够在保证隔离性的同时提高并发读写性能,是一种兼顾性能和数据完整性的重要技术。MVCC通过引入版本或者视图来实现可重复读,避免了读的时候加锁,只有在写的时候才进行加锁,从而提高了系统的性能。核心是通过引入事务ID、隐藏列、undo log、快照读、当前读等基本概念,建立读视图来实现可见性保证。MVCC的多版本控制策略基于undo_log和版本链的乐观控制并发的方式,可以为我们提供更好的性能,本质是通过快照读,完全不加锁而满足隔离性。文章最后提出了思考题,引发读者对MVCC在不同隔离等级下的实现方式和性能提升的思考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《业务开发算法 50 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(5)

  • 最新
  • 精选
  • demnox
    事务C更新id1会阻塞,因为事务B锁住了id1,只有事务B提交后,事务C才能继续执行
    2022-08-11归属地:重庆
    3
  • Geek_455ad8
    “如果不在数组中,说明在仍活跃着的事务范围内,但其中有一些事务虽然不是开始最早的,但是结束的却比活跃数组中的事务早,以至于当前事务开始时,这些事务已经结束,所以也应该是不可见的。” 这句话是不是写错了?难道不应该是可见的么?
    2022-07-04
    3
  • 功夫熊猫
    git,svn这些工具是不是也拿的mvvc算法
    2022-08-09归属地:江苏
  • peter
    老师辛苦了,请教几个问题啊: Q1:把 pointer 指向此前数据的 undo_log是谁做的? 讲undo log时,有一句话“所以每次新插入一条数据,除了插入数据本身和申请事务 ID,我们也要记得把 pointer 指向此前数据的 undo_log”,从这句话看,似乎“把 pointer 指向此前数据的 undo_log”是开发人员做的? 请问,这个操作是开发人员做的还是mysql自己做的? Q2:mysql的undo log除了用于事务和MVCC外,是否还有其他用途? Q3:读取加for update,一定会有幻读吗? Q4:读视图部分: A 处于中间部分的第二种情况是“如果不在数组中”: 既然“处于中间部分”,怎么会“不在数组”中呢? (处于中间的部分就要分类讨论了,下面两种情况XXX:我被这部分文字搞糊涂了。) B 事务C会加入到视图数组里面吗?
    2022-02-26
  • Paul Shan
    请问老师能否举一个例子,事务是不活跃的(不在当前视图事务数组中)但是事务id又是小于高水位大于低水位,多谢!我找到的例子,事务如果不活跃的,必然是在当前事务开启之前已经结束了,也就是处于低水位之前的。而在当前事务开启之后还没提交的都应该在当前视图事务数组中,例如文中最后一个例子事务B,即便到了T6,事务B已经提交,但是依然还在事务数组中。 RC通过MVCC比较好解决,只要把条件简化为trx_id < high_id,也就是可视窗口更大,但是感觉效率没提升多少,但是带来了不可重复读的问题。 MVCC依赖全局唯一而且递增的trx_id,只适用于单机版本,无法在网络环境下实现并发。
    2022-02-26
    1
收起评论
显示
设置
留言
5
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部