简单介绍
MVCC,Multi-Version Concurrency Control ,多版本并发控制。MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,以提高并发性能。
MVCC只在 读已提交(RC) 和 可重复读(RR) 两个隔离级别下工作。
其他两个隔离级别够和MVCC不兼容, 因为 READ UNCOMMITTED(读未提交) 总是读取最新的数据行, 而不是符合当前事务版本的数据行。而 SERIALIZABLE(可串行化) 则会对所有读取的行都加锁。
原理
MVCC基于undo log的版本链。在数据修改之前会把数据拷贝一份到undo log,同时为其添加三个隐藏字段,分别为db_trix_id(事务id)、db_roll_pointer(回滚指针)、**db_row_id(自增id)**默认为null,每次更新,都会将旧值加入undo log,事务id会自增,同时指针会指向前一次的旧值。随着更新次数增加,所有的版本都会被指针连接成一个链表,这就是版本链。
MVCC的另一个关键是ReadView,它是“快照读”SQL执行时MVCC提取数据的依据。
这里有两个概念简单理解一下:
快照读就是最普通的Select查询SQL语句
当前读指针对写操作的数据读取的方式:Insert、Update、Delete、Select…for update、Select…lock in share mode
ReadView是一个数据结构,包括四个字段
m_ids:当前活跃的事务编号
min_trx_id:最小活跃事务编号
max_trx_id:预分配事务编号,当前最大事务编号+1
creator_trx_id:ReaderView创建者的事务编号
在隔离级别RC下:在每次执行快照读的时候都会创建ReaderView,然后进行判断
● 如果当前事务id等于creator_trx_id,说明该数据是自己更改的,可以访问
● 如果当前事务id小于min_trx_id,说明数据已经提交了,可以访问
● 如果当前事务id大于max_trx_id,说明事务是在ReaderView生成之后开启,不能访问
● 如果min_trx_id<=当前事务id<=max_trx_id,则判断是否在m_ids,不存在则代表数据是已提交的,可以访问。
在隔离级别RR下:仅在第一次执行快照读的时候生成ReaderView,后续快照读复用,判断与RC一样,由于快照读复用,所以可重复读。
连续多次快照读,ReaderView会复用,不会产生幻读问题,但也有例外,当两次快照读之间如果存在当前读,ReaderView会重新生成,导致产生幻读。