MVCC 的一些总结
作者:互联网
解决问题
- MVCC(Multiversion Concurrency Control),多版本并发控制。MVCC 的目的是为了提高数据库并发性能,用更好的方式去处理读-写冲突、同时做到不加锁、非阻塞并发读写。
- MVCC 可以解决脏读、不可重复读,MVCC 使用快照读解决了部分幻读问题,而在当前读时还存在幻读问题,是通过临键锁解决的。
- 在 InnoDB 中 MVCC 本质是采用乐观锁思想的一种方式,而当前读是一种加锁的操作,是悲观锁的实现。
设计思路
- 使用 READ UNCOMMITTED 隔离级别的事务,由于可以读到未提交事务修改过的记录,所以直接读取记录的最新版本。
- 使用 SERIALIZABLE 隔离级别的事务,InnoDB 规定使用加锁的方式来访问记录。
- 使用 READ COMMITTED 和 REPEATABLE READ 隔离级别的事务,核心问题就是需要判断一下版本链中的哪个版本是当前事务可见的,这是 Read View 要解决的主要问题。
总结:只有在事务隔离级别 READ COMMITTED 和 REPEATABLE READ 下使用 MVCC。
实现思路
MVCC 的实现依赖于:隐藏字段、Undo log、Read View。
B+ 树上对应的记录只会有一个最新版本,但 InnoDB 可以根据 undo log 得到数据的历史版本,从而实现多版本控制。
那么每条行记录如何去找到关于它的 undo long 呢?
InnoDB 存储引擎中每条行记录都拥有两个隐藏的字段:trx_id 和 roll_pointer。trx_id 是最近更新这条行记录的事务 ID,roll_pointer 指向之前生成的 undo_log。
每次修改行记录都会更新 trx_id 和 roll_pointer 这两个隐藏字段,之前的多个数据快照对应的 undo log 会通过 roll_pointer 指针串联起来形成版本链。
Read View 包含四个字段:m_ids,min_trx_id,max_trx_id,creator_trx_id。
快照读与当前读
MVCC 主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读,而这个读指的就是快照读,而非当前读。
快照读:快照读又叫一致性读,读取的是快照数据,不加锁的简单的 SELECT 都属于快照读。
当前读:当前读读取的是记录的最新版本,加锁的 SELECT,或者对数据进行增删改都会进行当前读。需要注意的是,当前读是通过 next_key lock 锁防止幻读的。
Read View 的获取
- 在隔离级别为读已提交(Read Committed)时,一个事务中的每一次 SELECT 查询都会重新获取一次 Read View。如果 Read View 不同,就可能产生不可重复读或者幻读的情况。
- 当隔离级别为可重复读(REPEATABLE READ)时,一个事务只在第一次 SELECT 的时候会获取一次 Read View,而后面所有的 SELECT 都会复用这个 Read View。
标签:总结,加锁,快照,Read,trx,MVCC,一些,View 来源: https://www.cnblogs.com/zyb993963526/p/16428083.html