当前位置: 首页 > news >正文

Mysql 的事务隔离级别相关问题

MySQL 的事务隔离级别从低到高依次是:

  1. 读未提交(READ UNCOMMITTED)
    • 最低的隔离级别,允许事务读取其他事务未提交的数据(脏读)。
    • 存在 脏读不可重复读幻读 问题。
  2. 读已提交(READ COMMITTED)
    • 事务只能读取其他事务已经提交的数据,避免了脏读,但仍然可能会出现 不可重复读 问题。
    • 在同一个事务中,读取同一数据可能会得到不同的值。
  3. 可重复读(REPEATABLE READ)
    • 事务在其生命周期内多次读取相同数据时,结果保持一致,避免了 不可重复读 问题。
    • 但仍然可能会出现 幻读 问题。
    • MySQL 默认的隔离级别。
  4. 序列化(SERIALIZABLE)
    • 最高的隔离级别,强制所有事务串行执行,避免了 脏读不可重复读幻读
    • 为了确保事务串行执行,会通过加锁机制(如行级锁、表级锁等)避免并发。
    • 性能较差,适用于对数据一致性要求极高的场景。

总结:

  • 从低到高: READ UNCOMMITTED < READ COMMITTED < REPEATABLE READ < SERIALIZABLE

脏读、不可重复读和幻读是事务隔离级别下常见的并发问题,以下是它们的区别:

脏读(Dirty Read)

  • 定义:一个事务读取到另一个事务未提交的数据。
  • 发生情况:当事务A读取了事务B正在修改但尚未提交的数据,并且事务B之后发生回滚时,事务A读取到的数据是无效的。
  • 问题:脏读会导致事务A基于无效数据进行计算、决策,可能造成数据不一致。
  • 出现的隔离级别:在 READ UNCOMMITTED 级别下会发生脏读。

不可重复读(Non-repeatable Read)

  • 定义:在同一事务中,读取同一数据的两次查询结果不同。
  • 发生情况:事务A第一次读取数据后,事务B对同一数据进行了修改并提交。事务A再次读取数据时,得到的值与第一次读取时不同。
  • 问题:不可重复读会导致同一事务内的查询结果不一致,影响事务的逻辑判断。
  • 出现的隔离级别:在 READ COMMITTED 级别下会发生不可重复读,而 REPEATABLE READ 可以避免不可重复读。

幻读(Phantom Read)

  • 定义:一个事务读取到的记录集合,在其生命周期内发生了变化。
  • 发生情况:事务A在执行查询时,读取到一组符合条件的数据。随后,事务B插入、删除或修改了符合条件的数据。当事务A重新执行查询时,返回的数据集发生了变化(例如,原本没有某条数据,现在有了,或者原本有的数据,现在没有了)。
  • 问题:幻读会导致事务在读取数据时,查询结果不稳定,可能影响计算结果或业务逻辑。
  • 出现的隔离级别:在 REPEATABLE READ 隔离级别下可能发生幻读,而 SERIALIZABLE 隔离级别通过加锁可以避免幻读。

总结:

  • 脏读:读取到未提交的数据。
  • 不可重复读:同一事务中,读取相同数据时,结果不同。
  • 幻读:同一事务中,读取数据集合时,集合发生变化(例如插入或删除记录)。

这些问题的发生与事务的隔离级别紧密相关,较低的隔离级别容易发生这些问题,而较高的隔离级别(如 SERIALIZABLE)可以避免它们,但也会影响性能。

MySQL“读已提交”(READ COMMITTED) 隔离级别下,事务 T1 在不同的查询中可能会读取到不同的值,具体情况如下:

  1. T1 读取数据,获取的值为 A
  2. T2 修改数据,将其从 A 修改为 B,并 提交事务
  3. T1 再次读取 同一条数据,由于 “读已提交” 隔离级别确保每次查询都只能看到已经提交的数据,因此 T1 这次会读取到最新提交的值,即 B

结论:
READ COMMITTED 隔离级别下,T1 在同一事务内的两次读取可能会看到不同的值,第一次读取时获取的是 A,但当 T2 提交后,T1 再次读取时就会获取到 B。这种现象被称为 “不可重复读”(Non-repeatable Read)

如果 MySQL 的事务隔离级别设置为 可重复读(REPEATABLE READ),那么 T1 在同一个事务内的多次读取结果始终保持一致,不会受其他事务的提交影响。

  1. T1 读取数据,获取值 A
  2. T2 修改数据,将其从 A 修改为 B,并 提交事务
  3. T1 再次读取 这条数据,仍然会看到原来的值 A,不会看到 T2 提交后的值 B。

结论:
REPEATABLE READ 隔离级别下,T1 在同一事务内无论查询多少次,读到的数据都不会变化,始终是 事务开始时的快照数据,即 A
这种机制防止了 “不可重复读”(Non-repeatable Read) 的问题。

额外补充:
MySQL 的 InnoDB 存储引擎在 REPEATABLE READ 级别下,默认使用 MVCC(多版本并发控制) 来实现这一特性,使得即使 T2 提交了事务,T1 仍然可以读到事务开始时的快照数据,而不是最新提交的数据。

如果数据库的事务隔离级别是 读未提交(READ UNCOMMITTED),那么即使 T2 提交了事务T1 依然可能在 T2 提交前就已经读取到了 T2 的未提交数据,即 B

  1. T1 读取数据,获取值 A
  2. T2 修改数据,将其从 A 修改为 B,但 尚未提交事务
  3. T1 再次读取 这条数据,在 READ UNCOMMITTED 级别下,T1 可能会直接读取到 B,即使 T2 还未提交(即脏读)。
  4. T2 提交事务,此时数据正式变为 B
  5. T1 再次读取 这条数据,仍然会是 B,但问题是 T1 可能已经在 T2 提交之前就读取了 B,这意味着 T1 曾经发生过 脏读

READ UNCOMMITTED 隔离级别下:

  • T1 可能会在 T2 提交之前就读取到 T2 修改但未提交的数据(脏读)
  • T2 提交后,T1 继续读取数据,仍然是 B,但 T1 曾经发生过脏读,导致数据一致性风险

额外说明:

  • READ UNCOMMITTED 允许事务读取到其他事务未提交的数据,因此它的并发一致性最差,不推荐在生产环境使用。
  • 相比之下,READ COMMITTED 至少能避免脏读,因为它要求事务只能读取已提交的数据。

如果数据库的事务隔离级别设置为 序列化(SERIALIZABLE),那么 T1 和 T2 不能同时访问相同的数据行,因为 SERIALIZABLE 通过加锁 使事务 串行执行,从而避免所有并发事务导致的数据不一致问题。

  1. T1 开始事务,并读取数据,获取值 A
  2. T2 尝试修改数据,想将 A 修改为 B
    • 由于 SERIALIZABLE 级别会对读取的数据加“共享锁”(S锁),直到 T1 提交事务后才释放锁
    • T2 需要修改这条数据,因此会尝试获取“排他锁”(X锁),但由于 T1 还未提交,锁没有释放,T2 必须等待
  3. T1 再次读取数据,仍然是 A
  4. T1 提交事务后,T2 才能获取锁,修改数据为 B,并提交

结论:

  • 在 SERIALIZABLE 级别下,T1 在整个事务期间读取的数据不会被修改,确保了可重复读和一致性
  • T2 在 T1 事务提交前无法修改数据,只能等待 T1 释放锁
  • SERIALIZABLE 通过强制事务串行化执行,完全避免了脏读、不可重复读和幻读,但同时并发性能最差,适用于需要极高数据一致性的场景。

额外说明:

  • MySQL 的 InnoDB 存储引擎下,SERIALIZABLE 通过行级锁或间隙锁(Next-Key Lock)来实现,从而避免并发事务的冲突。
  • 由于 SERIALIZABLE 级别会降低并发性能,通常只在银行、财务等高一致性要求的场景下使用,日常业务中更常用 REPEATABLE READ 或 READ COMMITTED

相关文章:

  • SealOS部署k8s集群(单节点)
  • 视频推拉流EasyDSS案例分析:互联网直播/点播技术与平台创新应用
  • Spring Boot 3.x 引入springdoc-openapi (内置Swagger UI、webmvc-api)
  • 【毕业论文格式】word分页符后的标题段前间距消失
  • 面试题:实现学生管理系统
  • kotlin基础知识点汇总
  • 在Eclipse 中使用 MyBatis 进行开发,通常需要以下步骤:
  • UVC摄像头命令推流,推到rv1126里面去
  • MongoDB 数据导出与导入实战指南(附完整命令)
  • ClickHouse 通过 ​*ARRAY JOIN* 结合 ​Map 类型的内置函数取数值
  • 谷歌Chrome或微软Edge浏览器修改网页任意内容
  • AI大数据挖掘的威力
  • .NET下根据文件的哈希值筛选重复文件
  • 虚拟机下ubuntu进不了图形界面
  • STM32 HAL库实战:轻松实现串口通信驱动蓝牙模块与ESP8266开发
  • Spring Boot集成Mybatis中如何显示日志
  • RCE-Labs超详细WP-Level11Level12(0/1的特殊替换)
  • 安装操作系统ubuntu-20.04.6-live-server-amd64
  • Facebook 的框架及技术栈
  • FFmpeg —— 各系统下ffmpeg硬件加速和API支持情况(文内表格形式详细阐述)
  • 纽约市长称墨西哥海军帆船撞桥事故已致2人死亡
  • 台湾关闭最后的核电,岛内担忧“非核家园”缺电、涨电价困局难解
  • 墨西哥海军一载两百余人帆船撞上纽约布鲁克林大桥,多人落水
  • 专访|《内沙》导演杨弋枢:挽留终将失去的美好
  • 病重老人取钱在银行门口去世,家属:已协商一致
  • 现场丨在胡适施蛰存等手札与文献间,再读百年光华