1. 什么是MVCC

mvcc中文名位多版本并发控制,是数据库引擎处理读写冲突的一种手段,目的在于提高并发场景下数据库的吞吐量。
通过mvcc机制,在多个事务并发执行时,select可以无需加锁,而是通过mvcc机制读取指定版本的历史记录,可以保证读取的值符合事务所处的隔离级别。从而解决并发场景下的读写冲突。
在mysql数据库中,mvcc可以在读已提交可重复读两种隔离级别下使用。

2. 为什么需要MVCC

事务并发会导致一系列问题:丢失更新、脏读、不可重复读、幻读。数据库可以通过隔离级别来应对,实现隔离级别有两种方式:

  • 加读写锁
  • mvcc【针对于select,更新还得加写锁】

但本质上,隔离级别是一种在并发性能和并发产生的副作用间的妥协。

3. mvcc的实现原理

InnoDB引擎是通过每个表的两个隐藏字段实现的:

  • DATA_TRX_ID:记录更新这条记录的事务ID
  • DATA_ROLL_PTR:指向改行上一次的数据,在undo日志中以链表形式组织

此外InnoDB还有一个隐藏字段:

  • DB_ROW_ID:如果表没有主键,此列会出现作为隐藏主键。

MVCC的判断流程如下:

ReadView:是当前活动事务ID的列表[minid, maxid]

  • 如果被访问数据的DATA_TRX_ID小于minid,说明该版本的数据在ReadView生成前,已经提交,可以直接返回
  • 如果访问数据的DATA_TRX_ID大于maxid, 说明该版本的数据在ReadView生成后才生成,需要根据undo寻找上一个版本,继续判断
  • 如果访问数据的DATA_TRX_ID在minid和maxid之间,
    • 若DATA_TRX_ID在ReadView中,说明创建ReadView时,该版本所属事务尚未提交,需要寻找上一个版本
    • 若DATA_TRX_ID不在ReadView中,说明创建ReadView时,该版本所属事务已经提交,可以直接返回

RC和RR两个隔离级别下一个很大的不同是:ReadView生成时间点不同,RC下每次select都会生成一个ReadView,事务执行期间会更新;而RR只在第一个select语句时生成一个ReadView,事务执行期间,不会更新。

参考InnoDB MVCC 机制,看这篇就够了