深入解析:数据库事务详解

一.事务的ACID原则

1.原子性:

事务中的所有操作要么全部成功提交,要么在发生错误时全部回滚。

在这里插入图片描述

2.一致性:

事务对于修改操作,要求数据修改前和修改后的状态保持一致

3.隔离性:

一个事务的执行不会被其它事务干扰

隔离性是通过MVCC或锁机制来保证。

4.持久性:

一个事务一旦被提交,其修改会永久保存到数据库中

在这里插入图片描述

二.事务的隔离级别

1.读未提交

在这里插入图片描述

2.读已提交

在这里插入图片描述

3.可重复读:一个事务在执行的过程中,多次读取同一内容结果一致,可避免脏读和不可重复读,但幻读仍有可能发生。

4.串行化:最高的隔离级别,可以防止脏读、不可重复读以及幻读。

三.数据库并发事务,会带来哪些困难

  1. 脏读(Dirty Read):读取 “未提交” 的内容

定义:一个事务(T1)读取了另一个事务(T2)尚未提交的修改数据,而后续 T2 因异常回滚(Rollback),导致 T1 读取到的数据是 “无效的脏数据”。

核心问题:读的是 “临时数据”,数据最终可能被撤销,导致 T1 基于脏数据做的决策错误。

  • 仅在最低的 读未提交(Read Uncommitted)隔离级别下会发生;
  • 只要隔离级别提升到读已提交(Read Committed)及以上,脏读会被完全避免(因为只允许读取 “已提交” 的数据)。
  1. 不可重复读(Non-repeatable Read):同一事务内 “重复读不一致”

定义:一个事务(T1)在同一执行过程中,多次读取同一数据,但期间另一个事务(T2)修改并提交了该数据,导致 T1 前后两次读取的结果不一致。

核心问题:“同一事务内的读一致性” 被破坏 —— 事务期望 “一旦读取某数据,后续再读该内容时结果不变”,但实际被其他已提交事务修改。

  • 读已提交(Read Committed)级别下会发生(允许读取已提交数据,但不阻止其他事务修改);
  • 提升到 可重复读(Repeatable Read)级别后,会经过 “行锁” 或 “多版本并发控制(MVCC)” 避免 ——T1 读取后,其他事务无法修改该资料,直到 T1 结束。
  1. 幻读(Phantom Read):同一查询 “行数变化”

定义:一个事务(T1)在同一执行过程中,多次执行相同的范围查询(如 “查询库存 < 10 的商品”),期间另一个事务(T2)插入 / 删除了符合该范围的新内容并提交,导致 T1 前后两次查询的 “结果行数不一致”(像出现了 “幻影” 一样)。

核心障碍:“范围查询的一致性” 被破坏 —— 事务期望 “范围查询的结果集固定”,但实际因其他事务的增删,行数发生变化。

  • 可重复读(Repeatable Read)级别下可能发生(多数数据库如 MySQL 的 InnoDB 经过 “间隙锁” 优化,可减少幻读,但未完全杜绝极端场景);
  • 只有在最高的串行化(Serializable)级别下,才会凭借 “表锁” 完全避免 —— 事务串行执行,不允许并发修改,范围查询期间其他事务无法插入 / 删除符合条件的数据。
异常类型核心表现触发场景最低避免隔离级别
脏读读 “未提交” 数据其他事务修改未提交读已提交(Read Committed)
不可重复读同一行材料多次读结果不一致其他事务修改并提交同一行可重复读(Repeatable Read)
幻读同一范围查询多次读行数不一致其他事务插入 / 删除并提交新内容串行化(Serializable)

四.事务的隔离级别解决的问题

  1. READ_UNCOMMITTED
    事务读取:不加锁
    事务写入:加写锁
    解决问题:脏写
    存在问题:脏读,不可重复读、幻读。
  2. READ_COMMITTED
    事务读取:加读锁(每次 select 完成都会释放读锁)
    事务写入:加写锁
    解决问题:脏写、脏读
    存在问题:不可重复读、幻读。
  3. REPEATABLE_READ
    事务读取:加读锁(每次 select 完不会释放锁,而是事务结束后才释放)(如果是 Mysql 的 innodb 还会加间隙锁)。
    事务写入:加写锁
    解决问题:脏写、脏读、不可重复读,幻读(如果是 Mysql 的 innodb 则已解决)
    存在问题:幻读(如果是 Mysql 的 innodb 则不存在)。
  4. SERIALIZABLE
    不管读取还是修改所有的事务串行化执行,一个事务的执行必须等其他事务结束。
posted @ 2025-09-14 18:24  yfceshi  阅读(11)  评论(0)    收藏  举报