mysql 可重复读的实现原理

亮子 2022-10-28 08:09:39 10421 0 0 0

简述

MySQL默认的事务隔离级别是可重复读,即:事务A在读到一条数据之后,此时事务B对该数据进行了修改操作并提交,那么事务A再读该数据,依然还是原来的内容。 额,MySQL可重复读是如何做到的?

其实使用的是一种叫MVCC的控制方式 ,即Mutil-Version Concurrency Control(多版本并发控制),类似于乐观锁的一种实现方式。

实现细节

InnoDB在每行记录后面保存两个隐藏的列,分别保存了这个行的创建时间(版本号)和行的删除时间(版本号)。这里存储的并不是实际的时间值,而是系统版本号,当数据被修改时,版本号加1。
在读取事务开始时,系统会给当前读事务一个版本号,然后,事务会读取版本号<=当前版本号的数据。
此时如果其他写事务修改了这条数据(增删改),那么这条数据的版本号就会加1,从而比当前事务的版本号高,所以,当前事务读取的并不是更新后的数据,而是当前事务对应版本下的数据。

案例分析

假设初始版本号为1。

insert

insert into user (id,name) values (1,'Tom');

下面模拟一下文章开头的场景:

select(事务A)

select * from user where id = 1;

此时读到的版本号为1

update(事务B)

update user set name = 'Jerry' where id = 1;

在更新操作的时候,该事务的版本号在原来的基础上加1,所以版本号为2。
先将要更新的这条数据标记为已删除,并且删除的版本号是当前事务的版本号,然后插入一行新的记录

图片alt

select(事务A)

此时事务A再重新读数据:

select * from user where id = 1;

由于事务A一直没提交,所以此时读到的版本号还是为1,所以读到的还是Tom这条数据,也就是可重复读

delete

delete from user where id = 1;

在删除操作的时候,该事务的版本号在原来的基础上加1,所以版本号为3
删除时,将当前版本号作为删除版本号

图片alt