Skip to content

第七章:事务

1. 事务的价值

事务(Transaction)把一组读写操作封装成一个原子单元,目标是在故障与并发环境下给应用提供可控语义,减少“部分成功”带来的状态爆炸。

2. ACID 的工程含义

2.1 原子性(Atomicity)

事务要么全部提交,要么全部回滚。实现依赖 WAL、回滚日志或多版本机制。

2.2 一致性(Consistency)

ACID 里的一致性本质是“业务不变量成立”,主要由应用与约束共同保障,数据库只能提供检查与执行框架。

2.3 隔离性(Isolation)

并发事务互不干扰的程度。理想目标是可串行化,但实际常在性能与隔离之间折中。

2.4 持久性(Durability)

提交成功后,数据在崩溃后可恢复。单机依赖持久化日志,分布式依赖复制与恢复协议。

3. 多对象事务为何仍重要

单对象原子操作(如 CAS)无法覆盖跨行、跨表、跨索引约束。以下场景通常需要多对象事务:

  • 外键与唯一约束维护。
  • 多记录共同更新。
  • 二级索引与主数据同步更新。

4. 常见隔离级别与异常

4.1 Read Committed

避免脏读与脏写,但仍可能出现不可重复读与幻读。

4.2 Snapshot Isolation

事务从一致快照读取,读写互不阻塞,常通过 MVCC 实现。可显著提升读性能,但仍可能发生写偏差。

4.3 丢失更新(Lost Update)

典型 read-modify-write 并发覆盖问题。优先方案:

  • 原子更新语句。
  • SELECT ... FOR UPDATE
  • 自动冲突检测并重试。
UPDATE account
SET balance = balance - 100
WHERE id = 1;

4.4 写偏差与幻读

写偏差是“读取同一前提、更新不同对象”导致的不变量破坏,常由幻读触发。仅靠快照隔离通常不能完全避免。

5. 可串行化实现路线

5.1 串行执行(Serial Execution)

单线程按顺序执行事务,语义最直接。适合高性能内存场景,但跨分区事务代价高。

5.2 两阶段锁(2PL)

通过共享锁与排他锁实现悲观并发控制,可实现可串行化,但会带来阻塞、死锁与延迟抖动。

5.3 可串行化快照隔离(SSI)

基于快照隔离运行,在提交期检测危险依赖并中止冲突事务。读性能通常优于 2PL,是现代关系库常用折中。

6. 实务建议

  • 默认隔离级别不等于业务安全级别,关键路径要显式验证并发语义。
  • 以“可重试事务 + 幂等接口”设计上层逻辑。
  • 对高争用热点优先重构数据模型,避免把所有问题都压给锁。