MySQL的多版本并发控制(MVCC):
目录
readview:
判断的规则是:
快照读:
当前读:
优点:
MVCC(多版本并发控制)是一种通过维护数据行的多个版本来实现高并发机制,主要应用于InnoDB存储引擎。
在这之前需要的两个知识点是:
1.InnoDB存储引擎中行格式中有3个隐藏的列:
row_id:用于标识唯一一条数据记录。
trx_id:用于存储修改该数据行事务的id。
roll_pointer:存储的是一个指针,通过该指针找到回滚日志中的之前的数据记录。
2.undo log(回滚日志):
回滚日志中存储了该数据行修改之前的数据,形成版本链。
行格式中的roll_pointer指向undo log中的版本链,形成了一个单向链表。
MVCC的实现依赖于隐藏字段、undo log、readview(一致性视图)。
readview:
用于提供事务隔离级别的一致性读取视图,确保读操作在并发环境中访问数据快照时不受其他事务修改的影响。
一种逻辑视图,当事务启动时,会生成数据库系统当前的一个快照。InnoDB为每个事务构造了一个数组,用于记录维护系统当前的活跃事务id。基于事务id和回滚日志用于进行判断回滚日志版本链中的哪个版本对该事务可见。
生成的一个readview中,用creator_id来存储创建这个readview的事务id,只有写事务才会分配事务id,读事务的id默认为0。用trx_id表示生成readview时,当前系统中活跃的读写事务的事务id列表。up_limit_id存储当前活跃事务的最小事务id。low_limit_id存储生成系统因该分配给下一个事务的事务id(当前最大事务id+1)。
判断的规则是:
readview中的creator_id等于版本链中该数据记录的trx_id,也就是同一个事务,所以可以访问该版本的数据。
readview中的up_limit_id大于或者等于版本链中该数据记录的trx_id,表示生成该版本的事务在生成readview之前已经提交,所以可以访问该版本的数据。
readview中的low_limit_id小于版本链中该数据记录的trx_id,表示生成该版本的事务是在生成readview之后才开启,所以不能被访问。
readview中的trx_id集合中包含了版本链中该数据记录的trx_id,表示该事务处于活跃状态,不可访问,如果未包含并且在up_limit_id和low_limit_id之间,那么表明生成该版本的事务已提交,可以访问。
MVCC支持的隔离级别是提交读和可重复读。
提交读:
每一次查询都会生成一个readview,通过readview结合undo log和隐藏字段进行判断是否可读取,
就能够访问其他事务已提交的数据。
可重复读:
首次读取时生成一个readview,之后不再生成readview,确保多次查询的结果一致,避免不可重复读,也能够预防幻读。
快照读:
通过MVCC机制实现,读取事务启动时的数据,无锁非阻塞,降低了开销,如果在可串行化中,快照会退化为当前读。适用于普通的查询语句。
当前读:
通过锁机制实现,读取记录的最新版本,需要加锁保证一致性。适用于更新操作。
优点:
MVCC降低了死锁的概率,因为MVCC采用了乐观锁的方式,读取操作不需要加锁,对于写操作也只锁定必要行。解决了快照读的问题,保证了只能看到生成快照这个时间点之前的事务提交更新的结果,不会看到这个时间点之后的更新结果。解决了读写之间阻塞的问题,提高了事务的并发能力,读事务直接通过readview进行判断,所以读事务不会阻塞写事务,而写事务也不会阻塞读事务。