MVCC (Multi-Version Concurrency Control) 是MySQL中用于实现读已提交(Read Committed)和可重复读(Repeatable Read)隔离级别的一种机制。
MVCC 的核心是在每行记录后面保留旧版本的数据,同时在可能进行并发修改的行上维护一个版本链。这样,即使有事务在修改数据,也不会阻塞其他事务的读取操作。
以下是MVCC在MySQL InnoDB引擎中的工作机制概述:
在每行数据中保存额外的隐藏列来实现版本控制:
- DB\_TRX\_ID:插入或更新行的最后一个事务的ID
- DB\_ROLL\_PTR:指向之前版本数据的指针(仅在当前版本数据已经被删除或更改时使用)
- DB\_ROW\_ID:隐藏的自增行ID,在无显式ID的情况下用于唯一性检查
- 保存旧版本数据:当数据被修改时,原始数据保留在一个隐藏的历史数据列表中,称为版本链。
- 读取操作利用版本链:当进行查询时,MVCC会选择行的可见版本,即在当前事务开始时间点之前提交的最新数据版本。
插入、删除操作:
- 插入操作会创建一个新版本,其DB\_TRX\_ID设置为当前事务ID。
- 删除操作会创建一个新版本,其DB\_TRX\_ID设置为NULL,并且DB\_ROLL\_PTR指向被删除版本。
更新操作:
- 更新操作实际上是插入一个新行,并使旧行失效。
下面是一个简化的示例,说明MVCC如何工作:
| ID | NAME | DB_TRX_ID | DB_ROLL_PTR |
|----|-------|-----------|-------------|
| 1 | Alice | 10 | NULL |
| 2 | Bob | 20 | NULL |
假设有两个并发事务:T1和T2。
T1开始,读取Bob的信息:
- 读取时,MVCC选择了DB\_TRX\_ID为20的版本,显示Bob的信息。
T2开始,更新Bob的信息:
- 更新操作创建了一个新版本,DB\_TRX\_ID为30。
| ID | NAME | DB_TRX_ID | DB_ROLL_PTR |
|----|-------|-----------|-------------|
| 1 | Alice | 10 | NULL |
| 2 | Bob | 30 | NULL |
| 2 | Bob | 20 | 1 |
T1想再次读取Bob的信息:
- 此时MVCC选择的仍然是DB\_TRX\_ID为20的版本,因为它在T1开始之前就已经提交。
通过这种方式,MVCC允许在高并发环境下进行读-写操作,而不需要锁定整个表格。