后端工程师的高阶面经
邓明
前 Shopee 高级工程师,Beego PMC
6888 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
后端工程师的高阶面经
15
15
1.0x
00:00/00:00
登录|注册

13|MVCC协议:MySQL 在修改数据的时候,还能不能读到这条数据?

你好,我是大明。今天我们来学习 MySQL 面试中非常重要的一个内容—— MVCC 协议。
MVCC(Multi-Version Concurrency Control)中文叫做多版本并发控制协议,是 MySQL InnoDB 引擎用于控制数据并发访问的协议。它在面试中属于必面题,而且从 MVCC 出发能够将话题引申到事务、隔离级别两个重头戏上,所以掌握 MVCC 能让你进可攻退可守。
那么今天我就带你从 MVCC 的基本原理开始讲起,教你怎么在 MVCC 的面试中进退自如,秀出实力。在开始之前,我们先思考一个问题,为什么 InnoDB 会需要 MVCC?

为什么需要 MVCC?

你在前面已经学过了锁,知道锁本身就是用于并发控制的,那么为什么 InnoDB 还需要引入 MVCC,读写都加锁不就可以控制住并发吗?
锁确实可以,但是性能太差。如果是纯粹的锁,那么写和写、读和写、读和读之间都是互斥的。如果是读写锁,那么写和写、读和写之间依旧是互斥的。
数据库和一般的应用有一个很大的区别,就是数据库即便是读,也不能被写阻塞住。试想一下,如果一个线程准备执行 UPDATE 一行数据,如果这时候阻塞住了所有的 SELECT 语句,那么这个性能你能接受吗?
显然接受不了,所以数据库要有一种机制,避免读写阻塞。在理解了为什么 MVCC 必不可少之后,现在你需要进一步了解一个和 MVCC 紧密关联的概念:隔离级别
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

MySQL的MVCC协议是InnoDB引擎的重要协议,通过多版本并发控制提高了性能,避免了读写阻塞。隔离级别是MVCC的关键概念,MySQL有四个隔离级别,控制事务对其他事务的可见性。MVCC通过版本链和Read View实现多版本数据的管理和可见性规则。版本链通过trx_id和roll_ptr字段实现数据版本的串联,而Read View则控制事务应该读取哪个版本的数据。在面试准备中,需要了解公司数据库的隔离级别,并能应对关于MVCC的问题。MVCC协议通过版本链和Read View实现了高效的并发控制和数据可见性,为MySQL数据库的性能提供了重要保障。 文章重点介绍了MVCC的基本原理和隔离级别的调整,强调了已提交读隔离级别的重要性,并提供了应对可能需要可重复读隔禽级别的解决方案。此外,还提到了软技能面试相关的内容,强调了在推进某件事情时的策略,包括准备充分、公开决议、小步推进、全面铺开等四个步骤。 总的来说,文章内容涵盖了MVCC协议的基本原理、隔离级别的调整以及软技能面试相关的内容,为读者提供了全面的技术知识和面试准备建议。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《后端工程师的高阶面经》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(21)

  • 最新
  • 精选
  • sheep
    有一个加锁的问题? 可重复读由于加了next-key lock防止了幻读,这里加了锁叫next-key lock。 那读提交情况下,就不会加锁了么,都是靠read view来获取数据?update和delete下,读提交也不会加锁了么

    作者回复: update 和 delete 执行的时候会加锁,但是读的时候并不会。读会根据你的隔离级别直接去找历史数据来读。

    2023-10-11归属地:广东
    2
  • 梦倚栏杆
    是引入mvcc之后,对于读写来说,原来读加的读锁不再加了?还是说写锁加的逻辑时机变了?

    作者回复: 读锁要看你有没有主动启用。比如说你要是有 SELECT FOR UPDATE 的语句,那么读锁还是有的。 确实是变了,不再需要在最开始的时候就加锁了。

    2023-12-28归属地:北京
    1
  • rrbbt
    老师讲的确实很精彩,但有个问题没明白:可重复读的情况下,看不到别的事物的修改结果,当前事物还是基于老数据去修改,这时候最后的结果不会出问题吗?这个怎么解决呢?(我感觉mysql应该用读已提交才对啊,因为别人已经把数据改了,我再改的话,肯定得基于最新的数据去改啊,为什么mysql要默认设置成可重复读呢?)

    作者回复: 当然会出问题,而且这个问题臭名昭著。也就是,如果你有两个事务,假设说事务1 将name更新为 Tom,接下来事务 2 将 name 更新为 Jerry,那么就看谁最后提交,数据就是谁的。 因此为了避免这种更新丢失的问题,都是用乐观锁的,比如说数据带上版本号,update xxx set xxx where version = 123。这个版本号就是为了确保数据没被别的事务更改了。 用悲观锁也是可以的。 MySQL 为什么默认是可重复读,我猜测是 MySQL 认为可重复读更加满足贴近 ACID 特性中的隔离性要求吧。这方面倒是没见到官方说法。

    2023-07-14归属地:山东
    7
    1
  • 到不了的塔
    邓明老师,请问下,为什么mysql在读已提交隔离级别下会比可重复读隔离级别下性能更好? 比如不带锁的select语句查询,性能应该差不多吧,甚至可重复读的性能更好(因为可能不需要生成读快照)。

    作者回复: 在你举的例子里面,我倾向于赞同你的说法(虽然我没实验)。但是一般认为 RC 比较快是源自 RC 没那么多锁,比如说在文档里面 https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html 描述了,它比 RR 要少很多锁。

    2024-02-27归属地:上海
  • 起风了
    m_up_limit_id 在左边,而 m_low_limit_id 在右边 这块能再详细讲吗

    作者回复: 这个就是 innodb 的规定,没啥特别的理由。

    2024-01-04归属地:浙江
  • 梦倚栏杆
    感觉幻读和不可重复读是一回事,他俩的区别是啥呀?

    作者回复: 幻读肯定会造成不可重复读。但是幻读针对的是新数据,不可重复读针对的是老数据。

    2023-12-28归属地:北京
    2
  • okkkkk
    readview的几张图太棒了,很有收获,感谢

    作者回复: 加油加油!

    2023-11-29归属地:江苏
  • Geek_035c60
    已提交读,读已提交,是否可以统一一下称呼。

    作者回复: 能理解就行,本身在外面大家的说法就是各种混着喊。

    2023-11-16归属地:北京
  • 我得儿意的笑
    你好老师,在已提交读的情况下,直接读最后一次提交的数据就可以了,为什么还需要readview?

    作者回复: read view 是为了控制你能看到哪些数据。换言之,就是你得通过 read view 才知道别的事务已经提交了。

    2023-10-08归属地:上海
  • 浩仔是程序员
    老师你好,为什么可以同时多个事务修改同一条数据呢,第一个事务要修改时候不会对这条记录加锁吗?其他事务不是等待拿到锁?

    作者回复: 这里的同时,其实不是严格同一时刻。同一时刻确实是写操作在等锁。

    2023-09-03归属地:广东
收起评论
显示
设置
留言
21
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部