1. Home
  2. Docs
  3. 高性能MySQL
  4. mysql体系架构
  5. 多版本并发控制

多版本并发控制

多版本并发控制

大多数MySQL的事务存储引擎,如InnoDB、Falcon和PBXT,都没有使用简单的行锁定机制。相反,它们将行级锁定与一种称为多版本con-currency control(MVCC)的提高并发性的技术结合使用。MVCC不是MySQL独有的:Oracle、PostgreSQL和其他一些数据库系统也使用它。

您可以将MVCC看作是行级锁定的一种变种;在许多情况下,它完全避免了锁定的需要,并且可以有更低的开销。根据它的实现方式,它可以允许非锁定读取,而在写入操作期间只锁定必要的记录。

MVCC的工作原理是保持数据在某个时间点的快照。这意味着无论事务运行多长时间,都可以看到数据的一致视图。这也意味着不同的事务可以同时在同一个表中看到不同的数据!如果你以前从未经历过这种情况,它可能会让人困惑,但通过熟悉它会变得更容易理解。

每个存储引擎以不同的方式实现MVCC。其中一些变体包括乐观并发控制和悲观并发控制。我们将通过解释InnoDB行为的简化版本来说明MVCC的一种工作方式。

InnoDB通过每行存储两个额外的隐藏值来实现MVCC,这些值记录了行的创建时间和过期(或删除)时间。该行存储的不是这些事件发生的实际时间,而是每个事件发生时的系统版本号。这是一个每次事务开始时递增的数字。每个事务都保留其自己的当前系统版本的记录(从开始时起)。每个查询必须对照事务的版本检查每行的版本号。让我们看看当事务隔离级别设置为可重复读取时,这如何应用于特定操作:

SELECT
InnoDB必须检查每一行,以确保它符合两个标准:

InnoDB必须找到至少与事务相同的行版本(即其版本必须小于或等于事务版本)。这可以确保行在事务开始之前存在,或者事务创建或更改了行。
行的删除版本必须未定义或大于事务的版本。这样可以确保在交易开始前不会删除该行。

通过这两个测试的行可以作为查询结果返回。

INSERT
InnoDB用新行记录当前系统版本号。

DELETE
InnoDB将当前系统版本号记录为行的删除ID。

UPDATE
InnoDB使用新行版本的系统版本号写入该行的新副本。它还将系统版本号作为旧行的删除版本写入。

所有这些额外记录保留的结果是,大多数读取查询从不获取锁。他们只是尽可能快地读取数据,确保只选择符合条件的行。缺点是存储引擎必须在每一行中存储更多的数据,在检查行时做更多的工作,并处理一些额外的内务处理操作。MVCC仅适用于可重复读取和读取提交隔离级别。READ UNCOMMITTED与MVCC不兼容,因为查询不读取适合其事务版本的行版本;他们读的是最新版本,没有其他内容。SERIALIZABLE与MVCC不兼容,因为读取会锁定它们返回的每一行。