MySQL事务
事务是逻辑上的一组操作,要么都执行,要么都不执行。关系型数据库事务都有 ACID 特性:
适用场景:转账汇款、订单创建与库存扣减、多表联动更新等需要数据一致性的业务操作。当业务要求"全部成功或全部失败"时,必须使用事务。
- 原子性(Atomicity):事务是最小的执行单位,不允许分割。确保动作要么全部完成,要么完全不起作用
- 一致性(Consistency):执行事务前后,数据保持一致。例如转账业务中,无论事务是否成功,转账者和收款人的总额不变
- 隔离性(Isolation):并发访问时,一个用户的事务不被其他事务干扰,各并发事务之间数据库是独立的
- 持久性(Durability):事务提交后,对数据库中数据的改变是持久的,即使数据库发生故障也不应受影响
核心要点
MySQL事务与并发控制,包括ACID特性、隔离级别、MVCC原理
并发事务带来的问题
- 脏读(Dirty read):一个事务读取到另一个事务尚未提交的数据修改
- 丢失修改(Lost to modify):两个事务同时读取同一数据并修改,导致其中一个修改被覆盖
- 不可重复读(Unrepeatable read):同一事务内多次读取同一数据,结果不一致
- 幻读(Phantom read):同一事务内多次查询,发现多出或少了记录
不可重复读的重点是修改(值变化),幻读的重点是新增或删除(记录数变化)。
事务隔离级别
SQL 标准定义了四个隔离级别:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ-UNCOMMITTED | √ | √ | √ |
| READ-COMMITTED | × | √ | √ |
| REPEATABLE-READ | × | × | √ |
| SERIALIZABLE | × | × | × |
- READ-UNCOMMITTED(读取未提交):最低级别,允许读取尚未提交的数据变更
- READ-COMMITTED(读取已提交):允许读取并发事务已提交的数据,可阻止脏读
- REPEATABLE-READ(可重复读):对同一字段多次读取结果一致,可阻止脏读和不可重复读
- SERIALIZABLE(可串行化):最高级别,完全服从 ACID,所有事务依次逐个执行
MySQL InnoDB 默认使用 REPEATABLE-READ,不会有任何性能损失。InnoDB 的 REPEATABLE-READ 并不保证避免幻读,需要应用使用加锁读来保证,这个加锁读使用到的机制就是 Next-Key Locks。
分布式事务场景一般使用 SERIALIZABLE 隔离级别。
MVCC 实现原理
Multi-Version Concurrency Control(多版本并发控制),实现依赖于三个核心组件:
隐藏字段
DB_TRX_ID:6字节,最近修改事务 IDDB_ROLL_PTR:7字节,回滚指针,指向这条记录的上个版本DB_ROW_ID:6字节,隐藏的主键
Undo Log
回滚日志,在 insert、delete、update 操作时产生,用于回滚到之前版本。
Read View
三个全局属性:
trx_list:维护 Read View 生成时刻系统正活跃的事务 ID 列表up_limit_id:trx_list 中事务 ID 最小的值low_limit_id:Read View 生成时刻系统尚未分配的下一个事务 ID