知识全景图/ 软件工程与系统/ 如何设计业务数据库/ 事务、幂等与并发

如何设计业务数据库事务、幂等与并发

不要先背 ACID。先问:重复提交会不会多记一笔账。

这页只讲一件事:业务写接口怎样不重复、不覆盖、不半成功。

一、先看事故
事故根因设计动作
用户点一次,系统记两笔。弱网、刷新、重试都会重复提交。幂等键 + 请求 hash + 原结果引用。
幂等表成功,账目没写。幂等记录和业务写入不在同一事务。幂等记录、账目、审计同事务提交。
两个 worker 导入同一流水。都先查不到,再同时插入。唯一约束做最后防线。
两个窗口同时改账。后提交静默覆盖前提交。version 乐观锁或状态前置条件。
事务卡很久。事务里等通知、搜索、外部接口。主事务只保护事实,副作用走 Outbox / CDC。
判断:事务边界是“必须一起成功的事实”,不是把所有动作都塞进一个长事务。
二、一个写接口的最低设计
transaction: 1. insert idempotency record if absent 2. same key + same hash + succeeded -> return original entry_id 3. same key + different hash -> return conflict 4. insert entry 5. insert audit / outbox if needed 6. commit
三、三种保护别混用
工具挡什么
唯一约束重复导入、重复月结、同外部流水重复写。
乐观锁 version两个窗口同时编辑同一行。
状态前置条件worker 抢任务、订单推进、导入批次推进。
行锁 / 条件更新预算、余额、库存类原子判断。
Outbox / CDC主事务成功后的缓存、搜索、报表和通知。
四、验收规则
样本通过标准
同一新增请求发 10 次。只生成一条账目,重复请求返回同一结果。
两个 worker 同时导入同一流水。最多一个成功,另一个转成已存在。
两个窗口同时编辑。不会静默覆盖,必须提示版本冲突。
转账成功但响应丢失。重试不会再生成一组转账。
Outbox 消费失败后重启。主账目不重复,副作用可重放。
五、下一步
锁和死锁
继续看锁等待、死锁和有限重试。
导入重复
继续看批次、暂存行和去重键。
派生数据
继续看 CDC、Outbox 和派生一致性。
记住:幂等挡重复意图,唯一约束挡并发重复,版本检查挡静默覆盖,Outbox 把外部副作用移出主事务。