MySQL 事务详解

4 阅读4分钟

MySQL 事务(Transaction)是一组不可分割的数据库操作,要么全部执行成功,要么全部执行失败,是保证数据一致性、安全性的核心机制。

最典型的场景:银行转账(A扣钱、B加钱),必须两个操作同时成功/失败,不能出现A扣了钱B没收到的情况。


一、事务核心特性:ACID

事务必须严格满足 ACID 四大特性,这是事务的灵魂:

1. Atomicity(原子性)

  • 定义:事务是最小执行单元,要么全部成功,要么全部回滚失败,不允许中间状态。
  • 例子:转账 100 元,扣钱和加钱必须一起成功/一起失败。

2. Consistency(一致性)

  • 定义:事务执行前后,数据库的完整性约束不变,数据始终合法。
  • 例子:转账前后,两个人的总金额不变。

3. Isolation(隔离性)

  • 定义:多个事务并发执行时,互相不可干扰,一个事务看不到另一个事务的中间状态。
  • 事务隔离级别控制。

4. Durability(持久性)

  • 定义:事务一旦提交(COMMIT),数据永久生效,即使数据库崩溃也不会丢失。

二、事务的基本语法

MySQL 默认自动提交事务autocommit=1),手动控制事务语法如下:

-- 1. 开启事务
START TRANSACTION;  -- 或 BEGIN;

-- 2. 执行多条 SQL 操作
UPDATE account SET money = money - 100 WHERE name = 'A';
UPDATE account SET money = money + 100 WHERE name = 'B';

-- 3. 提交事务(所有操作永久生效)
COMMIT;

-- 4. 回滚事务(所有操作全部撤销,回到执行前状态)
ROLLBACK;

重要:自动提交开关

-- 查看自动提交状态
SELECT @@autocommit;  -- 1=自动提交 0=手动提交

-- 关闭自动提交(当前会话生效)
SET autocommit = 0;

三、并发事务带来的问题

如果不控制事务隔离性,多个事务同时操作同一份数据,会出现 4 类问题:

1. 脏读(Dirty Read)

一个事务读到了另一个事务未提交的修改,如果对方回滚,数据就是无效的。

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

同一个事务内,多次查询同一行数据,结果不一致(被其他事务修改并提交了)。

3. 幻读(Phantom Read)

同一个事务内,多次查询符合条件的记录总数不一致(其他事务插入/删除了数据)。

4. 丢失更新(Lost Update)

两个事务同时修改同一数据,后提交的覆盖先提交的修改,导致数据丢失。


四、事务隔离级别(重点)

MySQL InnoDB 引擎提供 4 种隔离级别,用来解决上面的并发问题,级别越高越安全、性能越低。

隔离级别脏读不可重复读幻读说明
READ UNCOMMITTED(读未提交)✅ 允许✅ 允许✅ 允许最低级别,基本不用
READ COMMITTED(读已提交)❌ 禁止✅ 允许✅ 允许互联网常用
REPEATABLE READ(可重复读)❌ 禁止❌ 禁止❌ 禁止MySQL 默认级别
SERIALIZABLE(串行化)❌ 禁止❌ 禁止❌ 禁止完全串行,性能极低

查看/设置隔离级别

-- 查看当前隔离级别
SELECT @@transaction_isolation;

-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

五、事务实现原理(简版)

InnoDB 依靠三大机制保证 ACID:

  1. redo log(重做日志):保证持久性,崩溃恢复数据
  2. undo log(回滚日志):保证原子性,回滚时撤销操作
  3. 锁 + MVCC(多版本并发控制):保证隔离性,实现高并发读写

六、事务使用注意事项

  1. 事务要短小精悍 长事务会锁定资源、占用日志空间,导致数据库性能下降。
  2. 避免在事务中做无关操作 不要在事务里调用外部接口、sleep、复杂计算,拉长事务执行时间。
  3. 提交/回滚必须明确 不要忘记 COMMIT 或 ROLLBACK,否则会导致锁不释放。
  4. 只在需要数据一致性时使用 单条 SQL 不需要手动开启事务(MySQL 自动封装为事务)。

总结

  1. 事务 = 一组不可分割的 SQL,要么全成,要么全败
  2. 核心 ACID:原子、一致、隔离、持久
  3. 并发问题:脏读、不可重复读、幻读
  4. 4 种隔离级别:MySQL 默认 可重复读(RR),互联网常用 读已提交(RC)
  5. 语法BEGIN → 操作 → COMMIT/ROLLBACK