事务
约 1138 字大约 4 分钟
2025-07-24
事务的四大特性与实现原理
原子性 (Atomicity)
- 定义:一个事务中的所有操作必须作为一个整体执行:要么全部成功并提交,要么全部失败并回滚。
- 实现原理:通过 Undo Log (回滚日志) 保证。事务开始时记录操作前的数据状态;若事务失败,系统基于 Undo Log 回滚到初始状态。
持久性 (Durability)
- 定义:事务一旦提交,对数据的变更是永久性的,即使在数据库故障恢复后,数据也不丢失。
- 实现原理:通过 Redo Log (重做日志) 保证。事务提交时先将操作日志刷新到持久存储;故障后重放 Redo Log 恢复数据。
隔离性 (Isolation)
- 定义:事务在提交前所做的修改对其他事务不可见,防止并发读/写冲突。
- 实现原理:通过锁机制(如共享锁/排他锁)和 MVCC (多版本并发控制) 实现。锁机制控制并发访问的顺序,MVCC 为每个数据行维护多个版本,基于事务时间戳控制可见性。
一致性 (Consistency)
- 定义:事务的执行必须使数据库从一个一致状态转换为另一个一致状态,遵守预定义约束(如唯一键或检查约束)。例如,转账操作中,事务前后的账户总额必须一致。
- 实现原理:作为 ACID 的目标,一致性通过实现原子性、持久性和隔离性而间接达到。
总结:原子性、持久性和隔离性是实现一致性的手段,一致性是最终目的。
事务并发问题
事务并发执行时可能导致数据不一致问题,常见问题如下:
- 脏读 (Dirty Read):一个事务读取到另外一个事务未提交的数据修改。例如,事务 B 读取事务 A 修改后但未提交的数据,如果事务 A 回滚,则事务 B 使用了脏数据。
- 不可重复读 (Non-repeatable Read):一个事务在同一个事务中多次读取同一条数据值,期间其他事务修改了该数据,导致前后结果不一致。例如,事务 B 先读取某行,事务 A 更新该行并提交后,事务 B 再读取同一行发现值变化。
- 幻读 (Phantom Read):一个事务执行相同范围查询两次,但其他事务插入或删除了符合条件的数据,使得第二次查询返回的行数变化。例如,事务 B 查询 salary > 10000 的员工数量,首次 10 条;事务 A 新增一条符合条件的记录并提交后,事务 B 再查询返回 11 条。
事务隔离级别与实现原理
事务隔离级别定义了事务之间的可见性与冲突处理策略,较低的级别提高并发但增加问题风险,较高的级别降低并发但减少问题。具体级别如下:
读未提交 (Read Uncommitted)
- 描述:事务未提交时,其变更操作对其他事务立即可见。
- 可能出现问题:脏读、不可重复读、幻读。
- 实现原理:无需特殊机制,直接读取最新数据版本。
读已提交 (Read Committed)
- 描述:事务提交后,其变更操作才能被其他事务读取(如 Oracle 默认级别)。
- 可能出现问题:不可重复读、幻读。
- 实现原理:通过 MVCC 实现。系统维护数据行快照,事务只读取已提交的版本快照。
可重复读 (Repeatable Read)
- 描述:事务中多次查询同一条数据时返回相同结果,即使以及被其他事务提交修改(MySQL InnoDB 默认级别)。
- 可能出现问题:按 SQL 标准可能出现幻读,但 MySQL 通过间隙锁优化后基本解决。
- 实现原理:通过 MVCC 和间隙锁 (Gap Locks) 实现。MVCC 保证查询基于事务开始点的快照;间隙锁阻止其他事务在查询范围内插入新数据,防止幻读。
串行化 (Serializable)
- 描述:事务完全串行执行,读写加锁阻塞并行访问。
- 可能出现问题:无(脏读、不可重复读、幻读均不会出现)。
- 实现原理:通过锁机制(如行级或表级读写锁)实现。读写操作冲突时,后访问事务等待前事务完成,确保顺序执行。