概述
当并发执行事务时,如何保证事务之间高效并按我们预想的情况执行?当有了这个问题的时候,MVCC都版本并发控制自然就诞生了
原理
Innodb会在每一张表多加三列隐藏列,分别为:
- 自增ID(DB_ROW_ID):新增数据时会生成的递增ID
- 事务ID(DB_TRX_ID):记录修改该条记录的事务ID
- 回滚指针(DB_ROLL_PTR):指向上一个版本的指针,用于回滚
实现依赖
mvcc的实现是依赖undo log和read view的:
- undo log :是存储一条数据被更改的多个版本的记录,回滚就靠它
- read view :用来判断当前版本数据的可见性
为了节省磁盘空间,innodb有专门的purge线程来清除已经不用的日志。purge会自动维护一个read view,为当前活跃事务最先开始的事务。如果某条记录最后修改的事务ID对该read view 是可见的话,并且进行了删除的标记,那么就会被清理
read view
read view 是读视图,也就是读进行时生成的快照,读视图里面维护这几个参数:
- 当前活跃事务的列表ID
- 列表中事务最小ID,也就是最先创建的事务
- 最大事务ID+1
我如何判断某个事务对我当前事务是否是可见的呢?
如果 A事务ID 小于 当前活跃事务最小ID那A事务对于当前事务来说就是可见的。
如果A事务ID 大于等于 当前活跃最大事务ID+1 那么说明A事务对该事务时不可见的
如果 A事务ID是否在活跃的事务列表ID中如果在,则代这个Read View生成时刻,A事务还在活跃,还没有Commit,修改的数据,我当前事务也是看不见的;如果不在,则说明,A事务在Read View生成之前就已经Commit了,你修改的结果,我当前事务是能看见的
对于RC(提交读)来说,相当于每一次读的时候进行一次快照读,第一次的快照跟后面的快照是不一样的,而对于RR(可重复读)来说,只是在事务一开始就会进行一次快照,后面读的时候使用的都是该快照。
水平有限,目前理解大致如此