多版本并发控制(MVCC)

MySQL 的大多数事务型存储引擎使用的都不是简单的行级锁机制。它们会将行级锁和可以提高并发性能的多版本并发控制(MVCC)技术结合使用

可以认为 MVCC 是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。根据其实现方式,不仅实现了非阻塞的读操作,写操作也只锁定必要的行

MVCC 的工作原理是使用数据在某个时间点的快照来实现的。这意味着,无论事务运行多长时间,都可以看到数据的一致视图,也意味着不同的事务可以在同一时间看到同一张表中的不同数据

InnoDB 通过为每个事务在启动时分配一个事务 ID 来实现 MVCC,该 ID 在事务首次读取任何数据时分配。在该事务中修改记录时,向 Undo 日志写入一条说明如何恢复该修改的 Undo 记录,并且事务的回滚指针指向该 Undo 日志记录。这就是事务如何在需要时执行回滚的方法。

当不同的会话读取聚簇主键索引记录时,InnoDB 会将该记录的事务 ID 与该会话的读取视图进行比较。如果当前状态下的记录不应可见(更改它的事务尚未提交),那么 Undo 日志记录将被跟踪并应用,直到会话达到一个符合可见条件的事务 ID。这个过程可以一直循环到完全删除这一行的 Undo 记录,然后向读取视图发出这一行不存在的信号。

事务中的记录可以通过在记录的 “info flags” 中设置 “deleted” 位来删除。这在 Undo 日志中也被作为“删除标记”进行跟踪。

值得注意的是,所有 Undo 日志写入也都会写入 Redo 日志,因为 Undo 日志写入是服务器崩溃恢复过程的一部分,并且是事务性的。这些 Redo 日志和 Undo 日志的大小也是高并发事务工作机制中的重要影响因素。

在记录中保留这些额外信息带来的结果是,大多数读取查询都不再需要获取锁。它们只是尽可能快地读取数据,确保仅查询符合条件的行即可缺点是存储引擎必须在每一行中存储更多的数据,在检查行时需要做更多的工作,并处理一些额外的内部操作

MVCC 仅适用于 REPEATABLE READ 和 READ COMMITTED 隔离级别

READ UNCOMMITTED 与 MVCC 不兼容,是因为查询不会读取适合其事务版本的行版本,而是不管怎样都读最新版本。

SERIALIZABLE 与 MVCC 也不兼容,是因为读取会锁定它们返回的每一行。

最后更新于