文章目录
- MySQL45讲 第八讲 事务到底是隔离的还是不隔离的?
- MVCC 实现原理
- 事务 ID 与数据版本
- 一致性视图
- 总结
MySQL45讲 第八讲 事务到底是隔离的还是不隔离的?
在 MySQL 的事务处理中,事务隔离级别与数据一致性是至关重要的概念。可重复读隔离级别看似使事务不受外界影响,但实际情况中事务间的相互作用却较为复杂。本文将深入探讨事务隔离级别的实现原理,包括 MVCC(多版本并发控制)机制、一致性读视图(read-view)的构建以及当前读与一致性读的区别。通过详细分析事务执行过程中的数据可见性规则,帮助读者理解事务之间的相互影响,以及如何在实际应用中避免可能出现的问题。
MVCC 实现原理
事务 ID 与数据版本
InnoDB 中每个事务V有唯一递增的 transaction id
,事务更新数据时生成新数据版本并记录row trx_id
。数据行可能存在多个版本(V1,V2,V3,V4),通过 undo log
(回滚日志)关联。
- 图中的三个虚线(U1, U2, U3)就是
undo log
一致性视图
事务启动时构造一致性视图 read-view,包含活跃事务 ID 数组,数组最小值为低水位,系统最大事务 ID 加 1 为高水位。数据版本可见性基于row trx_id
与一致性视图对比,分为已提交事务或自身生成(可见)、将来事务生成(不可见)、未提交事务生成(根据是否在数组中判断可见性)三种情况。
这样,对于当前事务的启动瞬间来说,一个数据版本的row trx_id
,有以下几种可能:
- 如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;
- 如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;
- 如果落在黄色部分,那就包括两种情况 :
- 若
row trx_id
在数组中,表示这个版本是由还没提交的事务生成的,不可见; - 若
row trx_id
不在数组中,表示这个版本是已经提交了的事务生成的,可见。
一个数据版本,对于一个事务视图来说,除了自己的更新总是可见以外,有三种情况:
- 版本未提交,不可见;
- 版本已提交,但是是在视图创建后提交的,不可见;
- 版本已提交,而且是在视图创建前提交的,可见。
总结
InnoDB的行数据有多个版本,每个数据版本有自己的row trx_id
,每个事务或者语句有自己的一致性视图。普通查询语句是一致性读,一致性读会根据row trx_id
和一致性视图确定数据版本的可见性。 对于可重复读,查询只承认在事务启动前就已经提交完成的数据; 对于读提交,查询只承认在语句启动前就已经提交完成的数据; 而当前读,总是读取已经提交完成的最新版本。