资料参考:https://blog.csdn.net/thesprit/article/details/112970122
https://www.bilibili.com/video/BV1t5411u7Fg?from=search&seid=11898621611946908479&spm_id_from=333.337.0.0
mvcc翻译过来叫多版本并发控制,主要针对事务隔离级别中的read commit读已提交和可重复读
首先我们要知道两个概念,一个叫快照读,一个叫当前读,快照读是实现是基于这个多版本并发控制的,那既然是多版本,那就可能读取的数据并不是最新的,不用上锁;而当前读是读取最新的数据,会上锁,而且是悲观锁
mvcc原理:
mvcc是基于版本链和read views来实现的
如下图所示,这就是版本链,在InnoDB中,一张表必须包含两个字段,trx_id和roll_pointer,trx_id : 事务字段,当一个事务去操作某个行的数据时,会将自己的事务Id赋值给trx_id字段,roll_pointer : 回滚指针,当一个事务更新了一个字段的时候,并不会直接删除掉之前的字段,而是将该指针指向之前的字段存储到undo blog
然后还有一个概念叫readView,他相当于一个保存活跃事务id的集合,什么叫活跃事务id呢,就是在本事务执行的时候,还有哪些事务正在进行且还没有提交的事务,他的作用就是控制你能看到版本链中哪条数据,他主要包含了几个概念:
- m_ids,哪些事务正在执行且还没有提交的事务id,就会保存在这里
- min_trx_id:m_ids中最小值
- max_trx_id:下一个要生成的事务id,因为事务id自增,那假设m_ids中最大的是60,则max为61
- creator_trx_id,每开启一个事务都会生成一个 ReadView,而 creator_trx_id 就是这个开启的事务的 id。读事务时为0
这样在访问某条记录时,只需要按照下边的步骤判断该记录在版本链中的某个版本(trx_id)是否可见
1、trx_id
3、m_ids列表中最小的事务id < trx_id < m_ids列表中最大的事务id 此处比如m_ids为[5,6,7,9,10]
①、若trx_id在m_ids中,比如是6,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问。
②、若trx_id不在m_ids中,比如是8:说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。
一句话说:当trx_id在m_ids中,或者大于m_ids列表中最大的事务id的时候,这个版本就不能被访问。