Mysql的MVCC
引擎: InnoDB
隔离级别:REPEATABLE READ,READ COMMITED
词汇表:
(1)MVCC:多版本并发控制
(2)行创建时间:第一个隐藏列,记录创建时的事务号,也就是记录哪个事务创建它的
(3)行删除时间:第二个隐藏列,记录执行删除该行的事务号,也就是记录哪个事务删除它的
优点:是大多数读操作不用加锁,提高并发能力
缺点:因为每行都要进行版本号记录比较,所以有更多的行检查操作与额外的维护工作
注意:删除的行只需要在行创建时间标明删除它的那个事务的版本号,但是它还是存在的,因此当你更新一条记录时,首先是在原来的记录添加事务版本号,然后插入一条新的记录
实现原理
通过保存数据在某一时刻的快照来实现,InnoDB是为每一行记录都添加两个隐藏列,分别用于记录创建时间与删除时间,然后每个事务都需要对比这两个时间与自己的版本号来选择是否要进行操作
1.SELECT:查询的行的创建版本号一定要小于或等于自身版本号,同时删除版本号一定要大于当前版本号(不然就是对于本事务就是已删除的记录无法查询)
本事务版本号为3的事务执行SELECT操作
因为d的创建时间晚于3,所以对于3来说还没出世,当然不能查询得到
因为c的删除时间早于3,所以对于3来说早就被删除了,不能查询得到
而导致这种情况的发生的根本原因就是事务并发进行且时间不一致,3事务还没执行完4事务就执行完了
2.INSERT
插入行,创建时间为该事务的事务版本号
3.DELETE
在该行修改删除时间为该事务的事务版本号
4.UPDATE
原来的行删除时间修改为该事务的事务版本号
新插入一行,创建时间为该事务的事务版本号
MVCC与脏读问题
脏读:未提交的事务所修改的数据对外可见
MVCC只在REPEATABLE READ和READ COMMITED两种隔离级别下工作,这两个隔离级别已经解决脏读问题;
只要事务未提交,那么UPDATE操作就不会生效,因此就没有脏读问题
MVCC与幻读问题
幻读:事务1查询了A~B范围的数据,然后事务2在该范围内插入新的一行然后提交,此时事务1再去访问就会发现多了一行数据
事务1执行第一次操作时的数据
事务2执行INSERT操作并提交后的数据
事务1再次执行查询操作,因为d的创建时间大于1,所以不能查询到,因此幻读问题被解决
《高性能Mysql》p13