Live2D

MVCC 是什么?InnoDB 是如何实现 MVCC 机制的?

概念

MVCC全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突。

解决问题

MVCC主要解决的问题是可以保证MySQL在读的时候不会阻塞写,在写的时候不会阻塞读(读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了, 不同的事务session会看到自己特定版本的数据);同时还能解决脏读、幻读、不可重复读。

如何实现

MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段undo log日志readView

三个隐藏字段:

这三个字段分别是:

  • DB_TRX_ID:表示写入该版本数据的事务 ID。

  • DB_ROLL_PTR:表示该数据行被删除或更新前的位置。

  • DB_ROW_ID:表示该数据行的 ID。

写/修改:当一个事务对某个数据行进行修改时,InnoDB 会将该数据行的旧版本存储到回滚日志中,并生成一个新版本,新版本的 DB_TRX_ID 字段存储当前事务的 ID,DB_ROLL_PTR 字段存储回滚日志中旧版本的位置,DB_ROW_ID 字段则为新生成的 ID。

并发读取:在并发读取时,如果某个事务读取了某个数据行的旧版本,但是当前该数据行已经被其他事务修改了,则该事务会通过 DB_TRX_ID 字段判断该版本是否可见,如果不可见则会读取当前可见的版本,如果可见则会继续读取该版本。这种机制可以有效地避免并发读取时的数据冲突。

在 InnoDB 中,为了实现 MVCC,还需要使用 undo log 和 read view 来存储数据。undo log 记录了每个事务对数据行进行修改的情况,read view 记录了每个事务开始时的数据版本号和当前系统时间,用于判断事务是否可以读取某个数据行的版本。当一个事务执行查询操作时,InnoDB 会根据 read view 来确定该事务能够读取到的数据版本号,并使用 undo log 来恢复该数据行的历史版本。

 

流程

  1. 在查询一条数据记录时,先会获取自己的事务ID

  2. 再根据生成的Read View的规则来判断其要访问的数据的版本是否允许被访问(当一个事务需要读取一行记录时,InnoDB 首先读取这行记录的创建时间和过期时间,并根据这些信息判断该行记录是否可见。如果创建时间早于当前事务的开始时间,且过期时间晚于当前事务的开始时间,那么该行记录对当前事务可见。)

  3. 如果不允许,需要使用Undo Log的版本链寻找到以前版本的数据

  4. 最后返回数据

 

注意

MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作。其他两个隔离级别够和 MVCC不兼容。已提交读和可重复读的区别就在于它们生成ReadView的策略不同。在读已提交的的事务隔离级别下,每次读取都会生成一个Read View来解决脏读的问题,在可重复度的隔离级别下,一个事务在第一次生成一次Read View,之后的查询都使用这个Read View,解决了不可重复读的问题。

posted @ 2023-03-06 17:24  都是朕的江山  阅读(309)  评论(0)    收藏  举报
返回顶端