关于MySQL的酸与MVCC和面试官小战三十回合

我,小Y。 此刻,正坐在办公室里等待面试,心情xue微有点忐忑,不知道待会儿老面试官经不经得住我的折磨。 只见一抹光亮闪过,面试官推门而入,我抬头望去,强者的气息铺面而来,没错是那味儿。 看到面试官头上那“傲然矗立”的头发,脑海中止不住幻想他在无数个凌晨于电脑前挑灯夜码的高大形象,一种敬佩感油然而生, 竟忍不住站起来给他敬了个礼。 面试官:有病? 我:没没没,我谢顶反应综合征犯了,面试官好,我是小 Y ,请多多指教。 面试官:哦哦,确实是有病啊,没事,记得吃药就行。我看你简历写你 MySQL 挺懂的,那我先问问你 MySQL 吧。 我:好嘞,您请。 面试官:你知道什么是 MySQL 的酸吗? 这一来就这么猛的吗?脑海中一顿搜索,只能想起张含韵的我喜欢酸的甜这就是真的我之《酸酸甜甜就是我》,算了蒙一个。 我:事务? 面试官:哟,最近好多谐音梗,我特意玩了个英语单词短语梗,脑子转的挺快啊小伙子。 酸,英文 acid,说的就是事务!这都蒙对了,等下就去买彩票!趁这个机会再表现一下! 我:是啊,国外的人就有拼凑单词的习惯,其实事务主要是为了实现 C ,也就是一致性,具体是通过AID,即原子性、隔离性和持久性来达到一致性的目的,所以这四个不应该相提并论,但是他们就想拼成单词,就把它们排好序搞在一起来念。 嘿嘿,这个B装的我有点舒服,果然面试官有点惊讶。 面试官:可以呀,那你知道 MVCC 吧? 我:知道,Multi-Version  Concurrency Control (多版本并发控制)。 面试官:能先简短的解释下什么是 MVCC 吗? 我:多版本并发控制,其实指的是一条记录会有多个版本,每次修改记录都会存储这条记录被修改之前的版本,多版本之间串联起来就形成了一条版本链。 这样不同时刻启动的事务可以无锁地获得不同版本的数据(普通读)。此时读(普通读)写操作不会阻塞,写操作可以继续写,无非就是多加了一个版本,历史版本记录可供已经启动的事务读取。 (为保持简短,简化了SQL语句,下文也同样简化) 面试官:那你知道事务四种隔离级别吧? 我:读未提交、读已提交、可重复读、可串行化。 面试官:MVCC 用来实现哪几个隔离级别? 我:用来实现读已提交和可重复读。首先隔离级别如果是读未提交的话,直接读最新版本的数据就行了,压根就不需要保存以前的版本。可串行化隔离级别事务都串行执行了,所以也不需要多版本,因此 MVCC 是用来实现读已提交和可重复读的。 面试官:那为什么需要 MVCC ?如果没有 MVCC 会怎样? 我:如果没有 MVCC 读写操作之间就会冲突。想象一下有一个事务1正在执行,此时一个事务2修改了记录A,还未提交,此时事务1要读取记录A,因为事务2还未提交,所以事务1无法读取最新的记录A,不然就是发生脏读的情况,所以应该读记录A被事务2修改之前的数据,但是记录A已经被事务2改了呀,所以事务1咋办?只能用锁阻塞等待事务2的提交,这种实现叫… Continue reading 关于MySQL的酸与MVCC和面试官小战三十回合

值得收藏,揭秘 MySQL 多版本并发控制实现原理

▲ 点击上方“架构精进之路”关注公众号 回复“01”领取「程序员进阶大礼包」 架构精进之路 十年研发风雨路,大厂架构师,CSDN博客专家。专注软件架构研究,技术学习与职业成长,坚持分享接地气儿的架构技术干货文章! 78篇原创内容 公众号   这是「架构精进之路」公众号的第73篇原创文章   MySQL 中多版本并发控制(MVCC),是现代数据库引擎实现中常用的处理读写冲突的手段,MVCC 作为 MySQL 高级应用特性,目的在于提高数据库高并发场景下的吞吐性能。 一、MVCC出现背景是什么? 事务的4个隔离级别以及对应的3种异常: 脏读:一个事务读取到了另外一个事务没有提交的数据; 不可重复读:在同一事务中,两次读取同一数据,得到内容不同; 幻读:同一事务中,用同样的操作读取两次,得到的记录数不相同。 在 MySQL 中,默认的隔离级别是可重复读,可以解决脏读和不可重复读的问题,但不能解决幻读问题。如果我们想要解决幻读问题,就需要采用串行化的方式,也就是将隔离级别提升到最高,但这样一来就会大幅降低数据库的事务并发能力。 而MVCC就是通过乐观锁的方式来解决不可重复读和幻读问题,它可以在大多数情况下替代行级锁,降低系统的开销。 MySQL 并发事务会引起更新丢失问题,解决办法是锁,主要分两类: 乐观锁: 其实现如同它的名字一样,是假设比较好的情况。 每次取数据的时候都认为他人不会对其修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。 悲观锁: 悲观锁也如同它的名字一样,总是假设比较坏的情况,每次取数据的时候都认为他人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。 二、什么是MVCC,它解决了什么问题? MVCC 是通过数据行的多个版本管理来实现数据库的并发控制,简单来说它的思想就是保存数据的历史版本。 我们可以通过比较版本号决定数据是否显示出来(具体的规则后面会介绍到),读取数据的时候不需要加锁也可以保证事务的隔离效果。 通过 MVCC 我们可以解决以下几个问题: (1)读写之间阻塞的问题,通过 MVCC 可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并发处理能力。 (2)降低了死锁的概率。这是因为 MVCC 采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。 (3)解决一致性读的问题。一致性读也被称为快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。 解释一下可能难以理解的几个词汇: 快照读: 读取的是快照数据,不加锁的简单的SELECT都属于快照读(只是普通的读操作)。 当前读: 当前读就是读取最新数据,而不是历史版本的数据。 加锁的SELECT,或者对数据进行增删改都会进行当前读(包括加锁的读取和DML操作)。 三、应用举例分析 为了更好地让大家理解MVCC,我们用一个示例场景来说明。 假设有个账户金额表 user_balance,包括三个字段,分别是 username… Continue reading 值得收藏,揭秘 MySQL 多版本并发控制实现原理