1、什么是MVCC
mvcc多版本并发控制。
mvcc在mysql innodb中主要是为了提高数据库并发性能,用更好的方式去处理读写冲突,做到即使有读写冲突时,也能做到不加索,非阻塞并发读。。
2、实现原理:
mvcc的实现是通过保存数据在某个时间点的快照来实现的。也就是说不管需要执行多长时间,每个事物看到的数据都是一致的。
3、mvcc解决那些问题?
事务并发可能会产生以下问题:
mvcc可以解决脏读、不可重复读,使用快照读解决了部分幻读问题,但是在修改时还是使用当前读,所以还是存在幻读问题,幻读问题最终就是使用间隙锁解决。
4、当前读和快照读
当前读:给读操作加上共享锁、排它锁,DML操作加上排它锁,这些都是当前读。当前读所读取的数据都是最新的,读取数据时加上锁,保证其它事物不能修改当前记录。
快照读:快照读的数据有可能不是最新的,而是之前版本的数据。
如何区分当前读和快照读
不加锁的简单的select都属于快照读;与之对应的则是当前读,给select加上共享锁、排它锁。
5、mvcc底层实现要素
在这之前需要知道MVCC只在REPEATABLE READ(可重复读) 和 READ COMMITTED(已读提交)这俩种隔离级别下适用。
mvcc实现原理是通过 隐藏字段(创建时版本号、回滚指针、删除版本号)、undo log 、Read view来实现的。
5.1、隐藏字段
在Innodb存储引擎中,在有聚簇索引的情况下每一行记录中都会隐藏俩个字段,如果没有聚簇索引则还有一个6byte的隐藏主键。
创建版本号:创建记录事务ID
删除版本号:删除/修改记录事务ID。这里只是将字段标记为删除状态。
回滚指针:指向记录上一个版本
5.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都属于一种类型,在事务回滚时需要,而且在快照读时也需要,则需要维护多个版本信息。只有在快照读和事务回滚不涉及该日志时,对应的日志才会被purge线程统一删除。
purge线程会清理undo log的历史版本,同样也会清理del flag标记的记录。
undo log 在mvcc中的作用就是 undo log 保存一个版本链,也就是上面回滚指针字段连接的。
当数据库执行select语句时会产生一致性试图read view。
read view是由查询时所有未提交事务ID组成的数组,数组中最小的事务ID为min_id和已创建的最大事务ID为max_id组成,查询的数据结果需要跟read-view做比较从而得到快照结果。
所以说undo log在mvcc中的作用就是为了根据存储的事务ID和一致性视图做对比,从而得到快照结果。
5.3、read view
当执行SQL语句查询时会产生一致性视图,也就是read-view,它是由查询的那一时间所有未提交事务ID组成的数组,和已经创建的最大事务ID组成的。
在这个数组中最小的事务ID被称之为min_id,最大事务ID被称之为max_id,查询的数据结果要根据read-view做对比从而得到快照结果。
于是就产生了以下的对比规则,这个规则就是使用当前的记录的trx_id跟read-view进行对比,对比规则如下。
5.3.1、版本链对比规则
如果落在trx_id 如果落在trx_id>max_id,表示此版本是由将来启动的事务生成的,是肯定不可见的 若在min_id<=trx_id<=max_id时 在这里还有一个特殊情况那就是对于已经删除的数据,在之前的undo log日志讲述时说了update和delete是同一种类型的undo log,同样也可以认为delete就是update的特殊情况。 当删除一条数据时会将版本链上最新的数据复制一份,然后将trx_id修改为删除时的trx_id,同时在该记录的头信息中存在一个delete flag标记,将这个标记写上true,用来表示当前记录已经删除。 在查询时按照版本链的规则查询到对应的记录,如果delete flag标记位为true,意味着数据已经被删除,则不返回数据。 小结 在同一个事务中进行查询,会沿用第一次查询语句生成的read-view(前提是隔离级别是在可重复读) 通过以上的四个案例,在版本链寻找过程中,可以总结出一个小技巧 技巧图 根据这个小技巧你可以很快的得知此版本是否可见。 总结 本文内容从浅到深,从什么是mvcc到mvcc的底层实现,一步一步地陈述了mvcc的实现原理。 本文简单总结