mysql MVCC
MVCC (multiversion concurrency control),多版本并发控制
-
MVCC代替行锁,降低系统开销
-
MVCC只对RR和RC隔离级别有影响。
-
不同的存储引擎实现MVCC的方式不同(乐观锁并发控制和悲观所并发控制)
-
InnoDB并不简单使用行锁,而是配合MVCC一起使用。
-
本文只探讨mysql InnoDB中MVCC的实现机制
MVCC具体实现
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现,分别为行的创建时间和删除时间。这里存储的并不是实际的时间值,而是系统版本号(可以理解为事务的ID)。每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID。
-
insert和update修改行的创建时间,每次操作会当前行的创建时间对应的值修改为当前事务的ID。
-
delete修改行的删除时间,每次操作会当前行的删除时间对应的值修改为当前事务的ID。
-
查询时将当前事务ID与所查找行的事务ID对应的创建时间和修改时间进行比较来判断是否可以读取当前行的数据。
-
比较条件:创建时间小于等于当前事务ID,删除时间大于等于当前事务ID
举例
-
假设user表中存在三条数据,对应的版本号(创建时间 1 删除时间 undefined)
-
事务A,系统版本号2:select * from user;比较版本号,因为创建时间1<=2所以此时会读取表中3条数据。
-
事务B, 系统版本号为3:insert into user...,插入一条数据,则新插入的行对应的创建时间为3。然后commit提交事务,事务结束。
-
事务A,系统版本号2:再次select * from user;比较版本号,因为创建时间3>2所以此时还是只能读取表中3版本号为1的3条数据。
-
事务C, 系统版本号为4:delete from user...,删除一条系统版本号为1的数据,则被删除的行对应的版本号(创建时间 1 删除时间 4)。然后commit提交事务,事务结束。
-
事务A,系统版本号2:再次select * from user;比较版本号,因为删除时间4>2所以此时能读到事务C中被删除的行。
-
综上举例,MVCC解决了幻读问题
此篇文章跟版本链和ReadView的方式有出入,谨慎选择。建议跳转第二个参考链接
参考