MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种数据库并发控制技术,用于在支持高并发访问时确保数据的一致性和隔离性。它允许多个事务同时读取数据库的同一份数据,而不互相阻塞,从而提高并发性能。在MySQL中,InnoDB存储引擎通过MVCC实现了非锁定读,使得读操作不会阻塞写操作,写操作也不会阻塞读操作。
MVCC的核心思想
MVCC的核心是为每一行数据维护多个版本,不同事务根据自己的隔离级别和开始时间,看到的数据可能是同一行的不同版本。这些版本通过隐藏的系统列(如trx_id
、roll_pointer
等)来区分。
MVCC的运作方式
MVCC的工作原理基于数据的多版本和事务的版本号。MySQL中的MVCC通过以下机制运作:
-
每个事务有一个唯一的版本号:
- 当事务开始时,InnoDB会给每个事务分配一个事务ID(
transaction ID
),它表示该事务的开始时间。 - 这个ID用于确保事务在处理过程中只看到特定版本的数据。
- 当事务开始时,InnoDB会给每个事务分配一个事务ID(
-
每行数据有两个隐藏字段:
- 创建版本号(
created_trx_id
):记录插入该行时的事务ID。 - 删除版本号(
deleted_trx_id
):如果该行被删除,记录删除该行的事务ID。如果未被删除,这个值为NULL。
这两个字段共同记录了数据的版本变化,通过这些隐藏字段,数据库可以保留多个版本的行数据。
- 创建版本号(
-
读取数据时:
- 当一个事务读取数据时,它会查看每一行的创建版本号和删除版本号。
- 事务只会读取那些满足以下条件的数据行:
- 行的创建版本号小于当前事务的ID(即这行数据在当前事务开始之前已经存在)。
- 行的删除版本号要么为NULL(表示该行尚未被删除),要么大于当前事务ID(表示该行在事务开始后被删除,事务不受影响)。
这意味着一个事务可以看到其他事务已提交的数据,但不会看到未提交的修改。
-
写数据时:
- 当一个事务更新或删除某一行数据时,InnoDB不会直接覆盖原有的数据行,而是创建该行数据的一个新版本。
- 原来的行会被标记为“已删除”(修改它的
deleted_trx_id
),而新的行将拥有自己的创建版本号。 - 这样,其他正在进行的事务仍然可以读取旧版本的数据,不会被影响。
MVCC的优势
-
非锁定读:读操作不需要加锁,避免了读和写的互相阻塞,显著提高了并发性能。特别是在隔离级别为可重复读或读已提交时,读操作不需要等待写操作完成。
-
提高并发性:由于读写操作互不阻塞,系统可以同时处理更多的事务,提高了数据库的吞吐量。
-
数据一致性:MVCC允许每个事务在其生命周期内看到一致的视图,即使其他事务在同时修改同样的数据。
不同隔离级别下的MVCC表现
-
读已提交(Read Committed):
- 事务在每次读取数据时,都会看到其他事务已经提交的最新版本。
- 这意味着,如果其他事务在中间提交了更新,当前事务会看到最新的变化,可能导致不可重复读。
-
可重复读(Repeatable Read):
- 事务在开始时会创建一个一致性视图,之后无论其他事务提交了多少次修改,当前事务都只能看到它开始时的数据状态。
- 这可以防止不可重复读问题,但仍可能出现幻读问题。
总结
MVCC通过为每行数据维护多个版本,实现了非锁定读,允许事务并发操作而不互相阻塞,从而提高了数据库的并发性能。每个事务只看到与自己隔离级别相对应的版本数据,保证数据的一致性和隔离性。