MySQL 中非锁定一致性读(MVCC)

1、简介

        非锁定一致性读是指InnoDB存储引擎通过多版本控制的方式来读取当前执行时间数据库中的数据。如果访问数据上锁了,在读取时不会因此去等待锁释放,而是去读取行的快照数据。具体原理如下图所示。

2、实现原理

         非锁定读是不需要等待访问的行上X锁释放,快照数据是指该行的之前版本的数据,通过undo log实现。每一行数据不止一个快照数据,每个快照都是一个记录版本,一般称这种技术为多版本技术,由此带来的并发控制,称之为多版本并发控制(MVCC)。MVCC只在REPEATABLE READ(可重复读) 和 READ COMMITTED(已读提交)这俩种隔离级别下适用。

2.1、当前读和快照读

当前读:给读操作加上共享锁、排它锁,DML操作加上排它锁,这些都是当前读。当前读所读取的数据都是最新的,读取数据时加上锁,保证其它事物不能修改当前记录。

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

如何区分当前读和快照读:不加锁的简单的select都属于快照读;与之对应的则是当前读,给select加上共享锁、排它锁。

2.2、MVCC实现

        MVCC是通过:隐藏字段(创建时版本号、回滚指针、删除版本号)、undo log 、Read view来实现的。

2.2.1、隐藏字段

        在Innodb存储引擎中,在有聚簇索引的情况下每一行记录中都会隐藏两个字段,如果没有聚簇索引则还有一个6字节的隐藏主键。

创建版本号:创建记录事务ID;

删除版本号:删除/修改记录事务ID。这里只是将字段标记为删除状态;

回滚指针:指向记录上一个版本。

2.2.2、undo log

        undo log 可以实现事务回滚操作来实现原子性,另外一个作用就是实现多版本控制 MVCC。undo log细分为两种:insert时产生的undo log;update和delete时产生的undo log。在Innodb中insert产生的undo log在提交事务之后就会被删除,因为新插入的数据没有历史版本,所以无需维护undo log。update和delete操作产生的undo log都属于一种类型,在事务回滚时需要,而且在快照读时也需要,则需要维护多个版本信息。

2.2.3、undo log回滚操作

        undo log 记录的是逻辑日志。当 delete 一条记录时,undo log 中会记录一条对应的 insert 记录,反之亦然,当 update 一条记录时,它记录一条对应相反的 update 记录,如果 update 的是主键,则是对先删除后插入的两个事件的反向逻辑操作的记录。

2.2.4、Read View

        Read View是事务进行快照读操作的时候生产的读视图,在该事务执行快照读的那一刻,会生成一个数据系统当前的快照,记录并维护系统当前活跃事务的id,事务的id值是递增的。RC 和 RR 隔离级别下,Read View 生成的时机不同(具体见2.3)。

        undo log 在MVCC中的作用就是保存一个版本链,也就是上面回滚指针字段连接的。当数据库执行select语句时会产生一致性视图read view。read view是由查询时所有未提交事务ID组成的数组,数组中最小的事务ID为min_id和已创建的最大事务ID为max_id组成,查询的数据结果需要跟read-view做比较从而得到快照结果。所以说undo log在mvcc中的作用就是为了根据存储的事务ID和一致性视图做对比,从而得到快照结果。

2.3、RC、RR 级别下的快照读不同点

1) 、在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照即Read View,将当前系统活跃的其他事务记录起来,此后在调用快照读的时候,还是使用的是同一个Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个Read View,所以对之后的修改不可见。

​ 2)、在RC级别下,事务每次快照读都会新生成一个快照和Read View;这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因。

​ 注:在RC隔离级别下,是每个快照读都会生成并获取最新的Read View;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View,之后的快照读获取的都是同一个Read View。

3、总结

        本文详细介绍MySQL中的MVCC机制,帮助大家理解在 RC 和 RR 隔离级别下为什么出现不可重复读、幻读等问题。进一步掌握MySQL日志功能。

        本人是一个从小白自学计算机技术,对运维、后端、各种中间件技术、大数据等有一定的学习心得,想获取自学总结资料(pdf版本)或者希望共同学习,关注微信公众号:it自学社团。后台回复相应技术名称/技术点即可获得。(本人学习宗旨:学会了就要免费分享)