题目重点:逐项连接转账不变量,区分数据库一致性与应用正确性,以及提交持久化和外部副作用。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练两个余额记录在同一支持事务的数据库;外部支付API不自动加入本地事务。
解题路线
- Atomicity是事务内部要么全部生效要么不生效,避免只扣A未加B;异常时回滚已纳入事务的动作,不等于撤销事务外发出的消息。
- Consistency是约束与应用不变量在合法事务后仍满足,例如总额守恒、余额约束。数据库能执行声明的约束,但错误业务SQL仍可能违反未声明逻辑,不能把C理解成所有代码自动正确。
- Isolation约束并发事务可观察到什么,不同级别允许不同异常;Serializable要求等价某串行次序,却可能以中止重试维持,不是所有请求都必定一次成功。
- Durability是成功提交后的状态在相应故障模型下保存,依赖日志、同步与配置;异步复制或未同步介质可改变机器损坏后的保证。接口响应先后需明确。
- 读后计算再无条件写可能丢失更新,需原子UPDATE、锁或版本检查。只写BEGIN并不确保所有业务并发条件都正确,隔离级别和重试边界必须一起讨论。
- 测试在多处注入故障:事务前、两写之间、提交前/后响应丢失;并发检查不变量,重试幂等,外部副作用用outbox等协议。不能用一次顺序转账证明隔离性。
手动走一遍
A转10给B,扣A和加B在一事务。加B之前异常应两者都不变;提交成功却响应丢失时客户端重试不能再次扣钱,需要请求幂等。不同事务同时读取A余额并扣款要防止覆盖。
规模与取舍
事务成本取决于读写集、锁等待、日志同步与重试;增加强隔离可提升保障但可能降低并发度,不能赋统一O(1)。
易错点与追问
容易失分的边界
- C等于所有应用逻辑必然正确。
- BEGIN便消除所有并发异常。
- 本地回滚可撤外部HTTP。
继续深挖
- 不同隔离级别怎样测试?
- 提交结果未知时如何查询?
- 跨库转账怎样补偿?
技术参考
- PostgreSQL Transaction Isolation:技术语义参考,具体题目按本文约定。
