MySQL学习笔记(2)并发问题与事务隔离级别

本文参考:https://javaguide.cn/database/mysql/transaction-isolation-level.html

并发事务问题

脏读:一个事务读到了另一个事务中未提交的数据

不可重复读:一个事务先后读取同一条数据,当时两次获取到的结果不同

幻读:一个事务按照条件查询数据时,没有查到对应的数据行,当时在插入数据时,又发现这行数据已经存在

SQL中标准的四个隔离级别:

  • 读取未提交(READ-UNCOMMITTED):允许读取尚未提交的数据变更。
  • 读取已提交(READ-COMMITTED):允许读取并发事务已经提交的数据。
  • 可重复读(REPEATABLE-READ):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改。
  • 可串行化 (SERIALIZABLE):所有的事务依次逐个执行。

    MySQL InnoDB 存储引擎的默认 支持的隔离级别是 REPEATABLE-READ(可重读),但是通过MVCC 机制和 Next-Key Lock 机制防止了幻读现象的出现。

InnoDB 的 MVCC 机制

InnoDB 使用多版本并发控制(MVCC)来实现一致性读。MVCC 的核心思想是:

  • 每个事务都有一个唯一的事务 ID(事务版本号)。
  • 数据行会保存多个版本(通过隐藏的列 DB_TRX_ID 和 DB_ROLL_PTR 记录版本信息)。
  • 事务读取数据时,会根据自己的事务 ID 看到数据在事务开始时的快照版本,而不是实时版本。

MVCC 如何防止幻读?

  • 在 REPEATABLE-READ 级别下,事务 A 的快照版本是固定的,它只能看到在事务开始时已经存在的数据行。
  • 即使其他事务插入了新行,这些新行不会出现在事务 A 的快照版本中,因此事务 A 不会看到这些新行,从而避免了幻读。

Next-Key Lock 机制

InnoDB 在 REPEATABLE-READ 级别下使用 Next-Key Lock 来进一步防止幻读。Next-Key Lock 是行锁(Record Lock)和间隙锁(Gap Lock)的结合:

  • 行锁(Record Lock):锁定已存在的数据行。
  • 间隙锁(Gap Lock):锁定数据行之间的间隙,防止其他事务插入新行。

Next-Key Lock 如何防止幻读?

  • 当事务 A 对某个范围的数据进行读取时,InnoDB 会使用 Next-Key Lock 锁定整个范围(包括已存在的行和行之间的间隙)。
  • 如果事务 B 尝试在这个范围内插入新行,会被间隙锁阻塞,直到事务 A 提交或回滚。
    这样,事务 A 在整个事务期间都能保证范围内的数据不会被其他事务插入新行,从而防止了幻读。

不可重复读和幻读的区别是一个读取的一行,一个读取的是多行吗?

不可重复读和幻读的区别并不是由读取单行或多行决定的,而是由数据变化的类型决定的。以下是两者的详细区别:

1. 不可重复读(Non-Repeatable Read)

不可重复读是指在同一个事务中,两次读取同一行数据时,数据的内容发生了变化。这种现象通常是由于其他事务对该行数据进行了更新(UPDATE)操作。

特点:
  • 数据行不变:数据行的主键或唯一标识没有变化。
  • 数据内容变化:数据行的内容(字段值)发生了变化。
  • 解决方法:通过记录锁(Record Lock)锁定数据行,防止其他事务更新该行。

2. 幻读(Phantom Read)

幻读是指在同一个事务中,两次读取同一范围的数据时,数据的集合发生了变化。这种现象通常是由于其他事务在该范围内插入(INSERT)或删除(DELETE)了数据行。

特点:
  • 数据范围不变:查询的条件范围没有变化。
  • 数据集合变化:查询结果集中出现了新的行或某些行消失了。
  • 解决方法:通过间隙锁(Gap Lock)或 Next-Key Lock(记录锁 + 间隙锁)锁定数据范围,防止其他事务在该范围内插入或删除数据。

3. 不可重复读 vs. 幻读

  • 不可重复读 :关注的是数据行的内容变化,通常是由于其他事务对同一行数据进行了更新操作。
  • 幻读 :关注的是数据范围内的集合变化,通常是由于其他事务在范围内插入或删除了数据。
相关推荐
jerry6092 分钟前
LLM笔记(六)线性代数
笔记·学习·线性代数·自然语言处理
ghost1436 分钟前
C#学习第23天:面向对象设计模式
开发语言·学习·设计模式·c#
weixin_4723394613 分钟前
MySQL MCP 使用案例
数据库·mysql
Yan_ks33 分钟前
计算机组成原理——数据的表示
学习
freellf1 小时前
go语言学习进阶
后端·学习·golang
真的想上岸啊1 小时前
学习51单片机02
嵌入式硬件·学习·51单片机
小刘要努力呀!1 小时前
嵌入式开发学习(第二阶段 C语言基础)
c语言·学习·算法
草莓熊Lotso1 小时前
【C语言字符函数和字符串函数(一)】--字符分类函数,字符转换函数,strlen,strcpy,strcat函数的使用和模拟实现
c语言·开发语言·经验分享·笔记·其他
IT从业者张某某2 小时前
信奥赛-刷题笔记-队列篇-T3-P3662Why Did the Cow Cross the Road II S
android·笔记
圈圈编码2 小时前
MVVM框架
android·学习·kotlin