二、MVCC 的概念及重要性
-
什么是 MVCC?
-
MVCC 的重要性
- 提高并发性能:MVCC 允许多个事务同时读取同一数据的不同版本,避免了事务之间的阻塞,从而提高了数据库的并发性能。
- 实现事务隔离级别:InnoDB 存储引擎通过 MVCC 实现了不同的事务隔离级别,如 READ COMMITTED 和 REPEATABLE READ。这些隔离级别保证了事务之间的独立性和数据的一致性。
- 支持长事务:在一些应用场景中,可能需要执行长时间的事务。MVCC 可以让长事务看到一致的数据视图,而不会被其他事务的修改所影响。
三、InnoDB 存储引擎中 MVCC 的实现原理
-
版本链
- InnoDB 存储引擎通过为每行数据保存多个版本,形成一个版本链。每当有事务对数据进行修改时,新的数据版本会被创建,并通过指针与旧版本链接起来。
- 例如,当事务 T1 对一行数据进行修改时,InnoDB 会创建一个新的数据版本 V2,并将其与旧版本 V1 链接起来。此时,版本链为 V1->V2。如果事务 T2 再次对该行数据进行修改,InnoDB 会创建一个新的数据版本 V3,并将其与版本 V2 链接起来,版本链变为 V1->V2->V3。
-
事务 ID 和隐藏列
- InnoDB 为每一行数据添加了两个隐藏列:一个是创建版本号(created_version),用于记录创建该行数据的事务 ID;另一个是删除版本号(deleted_version),用于记录删除该行数据的事务 ID。
- 当一个事务开始时,它会被分配一个唯一的事务 ID。在事务进行读写操作时,通过比较事务 ID 和行数据的版本号来确定可见性。
-
可见性判断规则
- 对于插入操作,新插入的数据版本的创建版本号为当前事务 ID。
- 例如,事务 T1 插入一行数据,该行数据的创建版本号为 T1 的事务 ID。
- 对于删除操作,将行数据的删除版本号设置为当前事务 ID。
- 例如,事务 T2 删除一行数据,该行数据的删除版本号被设置为 T2 的事务 ID。
- 对于更新操作,实际上是先删除旧版本的数据,再插入新版本的数据。
- 例如,事务 T3 更新一行数据,InnoDB 会先将旧版本的数据的删除版本号设置为 T3 的事务 ID,然后创建一个新的数据版本,并将其创建版本号设置为 T3 的事务 ID。
- 当一个事务读取数据时,会根据以下规则判断数据版本的可见性:
- 如果行数据的删除版本号大于当前事务 ID,表示该行数据已被其他事务删除,不可见。
- 如果行数据的创建版本号小于等于当前事务 ID,并且(行数据没有删除版本号或者删除版本号大于当前事务 ID),表示该行数据对当前事务可见。
四、MVCC 的优势详解
-
提高并发性能
-
实现事务隔离级别
- InnoDB 存储引擎通过 MVCC 实现了不同的事务隔离级别,如 READ COMMITTED 和 REPEATABLE READ。
- 在 READ COMMITTED 隔离级别下,事务只能看到已经提交的事务所做的修改。当一个事务读取数据时,它会根据当前事务 ID 和行数据的版本号来确定可见性。如果行数据的创建版本号小于等于当前事务 ID,并且行数据的删除版本号大于当前事务 ID 或者没有删除版本号,那么该行数据对当前事务可见。
- 在 REPEATABLE READ 隔离级别下,事务可以重复读取同一数据的相同版本,保证了事务的可重复读特性。InnoDB 存储引擎通过在事务开始时创建一个一致性视图(snapshot),来实现 REPEATABLE READ 隔离级别。一致性视图包含了事务开始时所有已经提交的事务的版本信息。当事务读取数据时,它会根据一致性视图和行数据的版本号来确定可见性。如果行数据的创建版本号小于等于一致性视图中的最小事务 ID,并且行数据的删除版本号大于一致性视图中的最大事务 ID 或者没有删除版本号,那么该行数据对当前事务可见。
-
支持长事务
- 在一些应用场景中,可能需要执行长时间的事务。例如,在数据分析和报表生成等场景中,可能需要对大量的数据进行复杂的查询和计算,这些操作可能需要花费很长时间才能完成。
- MVCC 可以让长事务看到一致的数据视图,而不会被其他事务的修改所影响。当一个长事务开始时,它会创建一个一致性视图。在事务执行过程中,它可以根据一致性视图和行数据的版本号来确定可见性。即使其他事务对数据进行了修改,长事务仍然可以看到它开始时的数据版本,从而保证了数据的一致性。
五、总结