MVCC:听说有人好奇我的底层实现(1)

简介: MVCC:听说有人好奇我的底层实现

MVCC实现原理

系列文章

前言

一、MVCC到底是什么?

二、悲观锁、乐观锁

1. 悲观锁(悲观并发控制)

2. 乐观锁(乐观并发控制)

三、MVCC解决了哪些问题

四、当前读、快照读

1. 当前读

2. 快照读

3. 如何区分当前读、快照读

五、MVCC实现三大要素

1. 隐式字段

2. undo log(回滚日志)

3. undo log底层实现

4. read-view

5. 版本链对比规则

六、MVCC底层原理

案例一

案例二

案例三

案例四

小结

七、总结




系列文章

1. 揭开MySQL索引神秘面纱

2. MySQL查询优化必备

3. 上来就问MySQL事务,瑟瑟发抖...

4. MVCC:听说有人好奇我的底层实现



前言

都知道事务的可重复读级别实现原理是使用MVCC实现的,那么你对MVCC的底层实现原理知道多少呢?面试高频点,你值得拥有。


一、MVCC到底是什么?

MVCC即多版本控制器,其特点就是在同一时间,不同事务可以读取到不同版本的数据,从而去解决脏读和不可重复读的问题。




这样的解释你看了不下几十遍了吧!但是你真的理解什么是多版本控制器吗?


生活案例:搬家


最近小Q跟自己的女朋友搬到新家,由于出小区的时候需要支付当月的物业费。


于是小Q跟自己的女朋友同时登录了小区提供的物业缴费系统。


悲观并发控制


假设小Q正在查当月需要缴纳的费用是多少进行支付的时候,此时小Q查询的这条数据是已经被锁定的。


那么小Q女朋友是无法访问该数据的,直至小Q支付完成或者退出系统将悲观锁释放,小Q的女朋友才可以查询到数据。


悲观锁保证在同一时间只能有一个线程访问,默认数据在访问的时候会产生冲突,然后在整个过程都加上了锁。


这样的系统对于用户来说就是毫无体验感,如果多个人同时需要访问一条信息,只能在一台设备上看喽!


乐观并发控制


在小Q查看物业费欠费情况,并且支付的同时,小Q的女朋友也可以访问到该数据。


乐观锁认为即使在并发环境下,也不会产生冲突问题,所以不会去做加锁操作。


而是在数据提交的时候进行检测,如果发现有冲突则返回冲突信息。


小结


Innodb的MVCC机制就是乐观锁的一种体现,读不加锁,读写不冲突,在不加锁的情况下能让多个事务进行并发读写,并且解决读写冲突问题,极大的提高系统的并发性


二、悲观锁、乐观锁

锁按照粒度分为表锁、行锁、页锁。


按照使用方式分为共享锁、排它锁。


根据思想分为乐观锁、悲观锁。


无论是乐观锁、悲观锁都只是一种思想而已,并不是实际的锁机制,这点一定要清楚。


1. 悲观锁(悲观并发控制)

悲观锁实际为悲观并发控制,缩写PCC。


悲观锁持消极态度,认为每一次访问数据时,总是会发生冲突,因此,每次访问必须先锁住数据,完成访问后在释放锁。


保证在同一时间只有单个线程可以访问,实现数据的排它性。同时悲观锁使用数据库自身的锁机制实现,可以解决读-写,写-写的冲突。


那么在什么场景下可以使用悲观锁呢!


悲观锁适用于在写多读少的并发环境下使用,虽然并发效率不高,但是保证了数据的安全性。


2. 乐观锁(乐观并发控制)

跟悲观锁一样,乐观锁实际为乐观并发控制,缩写为OCC。


乐观锁相对于悲观锁而言,认为即使在并发环境下,外界对数据的操作不会产生冲突,所以不会去加锁,而是会在提交更新的时候才会正式的对数据冲突与否进行检测。


如果发现冲突,要么再重试一次,要么切换为悲观的策略。


乐观并发控制要解决的是数据库并发场景下的写-写冲突,指用无锁的方式去解决


三、MVCC解决了哪些问题

在事务并发的情况下会产生以下问题。


脏读:读取其它事务未提交的数据。

不可重复读:一个事务在读取一条数据时,由于另一个事务修改了这条数据并且提交事务,再次读取时导致数据不一致

幻读:一个事务读取了某个范围的数据,同时另一个事务新增了这个范围的数据,再次读取发现俩次得到的结果不一致。

MVCC在Innodb存储引擎的实现主要是为了提高数据库并发能力,用更好的方式去处理读–写冲突,同时做到不加锁、非阻塞并发读写。


mvcc可以解决脏读,不可重复读,mvcc使用快照读解决了部分幻读问题,但是在修改时还是使用当前读,所以还是存在幻读问题,幻读问题最终就是使用间隙锁解决。


四、当前读、快照读

在了解MVCC是如何解决事务并发带来的问题之前,需要先明白俩个概念,当前读、快照读。


1. 当前读

给读操作加上共享锁、排它锁,DML操作加上排它锁,这些操作就是当前读。


共享锁、排它锁也被称之为读锁、写锁。


共享锁与共享锁是共存的,但是要修改、添加、删除时,必须等到共享锁释放才可进行操作。


因为在Innodb存储引擎中,DML操作都会隐式添加排它锁。


所以说当前读所读取的记录就是最新的记录,读取数据时加上锁,保证其它事务不能修改当前记录。


2. 快照读

如果你看到这里就默认你对隔离级别有一定的了解哈!


快照读的前提是隔离级别不是串行级别,串行级别的快照读会退化成当前读。


快照读的出现旨在提高事务并发性,其实现基于本文的主角MVCC即多版本控制器。


MVCC可以认为是行锁的一个变种,但是它在很多情况下避免了加锁操作。


所以说快照读的数据有可能不是最新的,而是之前版本的数据。


为什么要提到快照读呢!因为read-view就是通过快照读生成的,为了防止后文概念模糊,所以在这里进行说明。


3. 如何区分当前读、快照读

不加锁的简单的select都属于快照读。


select id name user where id = 1;


与之对应的则是当前读,给select加上共享锁、排它锁。


select id name from user where id = 1 lock in share mode;
select id name from user where id = 1 for update;
相关文章
|
4月前
|
安全 Java 容器
【Java集合类面试二十七】、谈谈CopyOnWriteArrayList的原理
CopyOnWriteArrayList是一种线程安全的ArrayList,通过在写操作时复制新数组来保证线程安全,适用于读多写少的场景,但可能因内存占用和无法保证实时性而有性能问题。
|
6月前
|
人工智能 Java API
面试官:谈谈对SpringAI的理解?
面试官:谈谈对SpringAI的理解?
70 0
面试官:谈谈对SpringAI的理解?
|
7月前
|
Java
面试官:说一说CyclicBarrier的妙用!我:这个没用过...
【5月更文挑战第5天】面试官:说一说CyclicBarrier的妙用!我:这个没用过...
48 2
|
Java C++
说一下 synchronized 底层实现原理?(高薪常问)
说一下 synchronized 底层实现原理?(高薪常问)
113 2
|
存储 算法 NoSQL
面试被问到MySQL索引,别再说不了解了,看完这篇你可以说个不停
面试被问到MySQL索引,别再说不了解了,看完这篇你可以说个不停
|
消息中间件 算法 JavaScript
面试官:谈谈分布式一致性机制,我一脸懵逼。。
面试官:谈谈分布式一致性机制,我一脸懵逼。。
|
存储 算法 关系型数据库
面试官:索引是什么,如何实现?懵逼~
面试官:索引是什么,如何实现?懵逼~
|
JavaScript 小程序 Java
面试官:Hash 碰撞是什么?如何解决?被问懵了……
面试官:Hash 碰撞是什么?如何解决?被问懵了……
|
安全 Java
不懂什么是锁?看看这篇你就明白了(四)
Java 中的锁有很多,可以按照不同的功能、种类进行分类,下面是我对 Java 中一些常用锁的分类,包括一些基本的概述
89 0
不懂什么是锁?看看这篇你就明白了(四)
|
存储 安全 Java
不懂什么是锁?看看这篇你就明白了(三)
Java 中的锁有很多,可以按照不同的功能、种类进行分类,下面是我对 Java 中一些常用锁的分类,包括一些基本的概述
93 0
不懂什么是锁?看看这篇你就明白了(三)