MySQL45讲 第八讲 事务到底是隔离的还是不隔离的?

时间:2024-11-06 08:01:30

文章目录

  • 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,有以下几种可能:

  1. 如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;
  2. 如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;
  3. 如果落在黄色部分,那就包括两种情况 :
  • row trx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见;
  • row trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。

一个数据版本,对于一个事务视图来说,除了自己的更新总是可见以外,有三种情况:

  1. 版本未提交,不可见;
  2. 版本已提交,但是是在视图创建后提交的,不可见;
  3. 版本已提交,而且是在视图创建前提交的,可见。

总结

InnoDB的行数据有多个版本,每个数据版本有自己的row trx_id,每个事务或者语句有自己的一致性视图。普通查询语句是一致性读,一致性读会根据row trx_id和一致性视图确定数据版本的可见性。 对于可重复读,查询只承认在事务启动前就已经提交完成的数据; 对于读提交,查询只承认在语句启动前就已经提交完成的数据; 而当前读,总是读取已经提交完成的最新版本。