概念
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 来恢复该数据行的历史版本。
流程
-
在查询一条数据记录时,先会获取自己的事务ID
-
再根据生成的Read View的规则来判断其要访问的数据的版本是否允许被访问(当一个事务需要读取一行记录时,InnoDB 首先读取这行记录的创建时间和过期时间,并根据这些信息判断该行记录是否可见。如果创建时间早于当前事务的开始时间,且过期时间晚于当前事务的开始时间,那么该行记录对当前事务可见。)
-
如果不允许,需要使用Undo Log的版本链寻找到以前版本的数据
-
最后返回数据
注意
MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作。其他两个隔离级别够和 MVCC不兼容。已提交读和可重复读的区别就在于它们生成ReadView的策略不同。在读已提交的的事务隔离级别下,每次读取都会生成一个Read View来解决脏读的问题,在可重复度的隔离级别下,一个事务在第一次生成一次Read View,之后的查询都使用这个Read View,解决了不可重复读的问题。
标签:事务,读取,InnoDB,版本,MVCC,机制,数据,ID From: https://www.cnblogs.com/galo/p/17184694.html