MySQL MVCC
什么是MVCC
多版本并发控制,实现一个数据的多个版本,解决事务在不同隔离级别下的读写冲突重要概念
当前读
获取的数据是最新的数据,同时在读取的时候要进行加锁保证其他事务不能进行修改;快照读
获取的数据可能是最新的数据,也可能是以前的版本;什么隔离级别会采用MVCC
- 读已提交的
- 可重复读
多版本原理
每行记录会隐性增加3个字段 DB_TRX_ID(事务id 记录当前记录是由哪个事务修改的)、 DB_ROLL_PTR(回滚指针 指向该记录的上一个版本记录的指针)、 DB_ROW_ID(自增id 没有主键的时候才会生成)比如:事务1来修改数据的时候,会将当前数据记录到undo log日志里面,当前数据的事务id字段会变成事务1,回滚指针指向刚才记录到undo log日志里面的那个版本;事务2来修改数据的时候,又会把事务1的数据记录到undo log日志里面,当前数据事务id变成事务2,回滚指针指向undo log日志里面的事务1的那个版本记录;undo log日志类似记录数据版本的链表,链首是最新的旧记录,链尾是最早的旧记录,当事务提交的时候undo log日志并不会马上删除,而是进入待清理,数据库会有一个purge线程来判断是否有其他事务在使用当前undo log日志上面的版本记录,如果没有使用才会进行清理;

如何解决读写冲突
当事务来进行读操作的时候,会生成数据库当前的一个快照,记录并维护系统当前活跃的事务id(事务id都是递增的,id越大说明事务越新);
当进行读快照的时候,对符合的记录生成Read View(读视图),并根据可见性算法判断是否可见,Read View自身维护了三个变量
- 当前系统活跃的事务id集合 trx_list
- 活跃集合中最小的事务id low_trx_id
- 系统尚未分配的下一个事务id high_trx_id
可见性算法:
Read View 会将数据记录的事务id(DB_TRX_ID)与low_trx_id进行对比,如果 DB_TRX_ID < low_trx_id说明该行记录在当前事务开启的时候已经commit了,所以对于当前事务来说是可见的;如果 DB_TRX_ID >= low_trx_id则进入到下一个判断;
DB_TRX_ID >= low_trx_id && DB_TRX_ID < high_trx_id :DB_TRX_ID与trx_list集合中的事务id进行对比,如果不存在则说明该DB_TRX_ID已经commit了,所以对于当前事务可见;反之说明DB_TRX_ID还未commit,则通过DB_ROLL_PTX找到上一个版本数据并获取DB_TRX_ID再次进行可见性算法;
DB_TRX>=high_trx_id:说明当前DB_TRX_ID是在快照后生成的,所以不可见,根据DB_ROLL_PTX找到上一个版本的数据并且获取该版本的DB_TRX_ID再次进行可见性算法;
读已提交(RC)和可重复读(RR)有什么不同
读已提交的是每次在快照读的时候都会生成不同的Read View;
可重复读则是同一个事务在第一次进行快照度的时候才会生成Read View,后面再去读取都是同一个Read View