什么是mvcc?
mvcc (多版本控制)指的是在读已提交、可重复读隔离级别下事务通过select查询访问版本链的过程,两者的区别是在于生成readView的时机不同,读已提交每次都生成新的readView,可重复读是在第一次生成,后面都重复使用。
版本链
在MySQL在innodb 存储引擎下每行记录包含了两个隐藏的列事务Id,回滚指针,事务创建时数据库会生成一个自增的事务ID,回滚指针存放上一条数据的地址,这样组成一个链表。
ReadView
MySQL 在读已提交、可重复读隔离级别下,开始事务执行查询时生成ReadView 。然后根据版本链控制当前记录是否可查询
主要包含以下四个内容
-
m_ids:表示在生成ReadView时当前系统中活跃的事务id列表
-
min_trx_id:表示在生成ReadView时当前系统中活跃的读写事务中最小的事务id,也就是m_ids中的最小值。
-
max_trx_id:表示生成ReadView时系统中应该分配给下一个事务的id值。
-
creator_trx_id:表示生成该ReadView的事务的事务id。
注意max_trx_id并不是m_ids中的最大值,事务id是递增分配的。比方说现在有id为1,2,3这三个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4。
有了这个ReadView,这样在访问某条记录时,只需要按照下边的步骤判断记录的某个版本是否可见:
-
如果被访问版本的trx_id属性值与ReadView中的creator_trx_id值相同,意味着当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问。
-
如果被访问版本的tx_id属性值小于ReadView中的min_trx_id值,表明生成该版本的事务在当前事务生成ReadView前已经提交,所以该版本可以被当前事务访问。
-
如果被访问版本的trx_id属性值大于ReadView中的max _trx_id值,表明生成该版本的事务在当前事务生成ReadView后才开启,所以该版本不可以被当前事务访问。
-
如果被访问版本的trx_id属性值在ReadView的min_trx_id和max_trx_id之间,那就需要判断一下tirx_id属性值是不是在m_ids列表中,如果在说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建ReadView时生成该版本的事务已经被提交,该版本可以被访问。