原子性
Atomicity
高级通用原子性(Atomicity)指一组操作在约定范围内要么全部生效,要么全部不生效。它解决的是操作做到一半就失败时留下不完整数据的问题,例如创建订单和扣减库存不能只完成其中一步。
你可能会说:「帮我把创建订单和扣库存绑在一起,别出现订单建好了、库存却没扣的情况。」
动手看看下单时订单与库存一起生效
1
用户下单后,订单服务开启一个事务,把创建订单和扣减库存放进同一次提交里。
要点原子性是怎么避免只做一半的?
- 1
先划定哪些操作算一组
你得先说清楚哪些变化必须一起成功。比如下单时创建订单、扣减库存都写在同一个数据库里,就可以把这两步放进一个事务;其中一步失败,整组数据库修改就回滚。
- 2
以提交作为生效的分界
事务提交前,系统还可以放弃这一组修改;提交成功后,这组修改才算完成。这样做的好处是,代码执行到第二步时报错,不会把第一步留下来当作一笔完成的业务。
- 3
看清事务管不到的地方
数据库事务不会顺手撤销已经发出的邮件或第三方支付请求。如果流程还涉及这些动作,我们就得另外设计失败后的处理方式,而不是以为包上一层事务就能全部回滚。
容易混淆的地方
原子性关心的是一组操作会不会只生效一部分;幂等关心的是同一个请求重复执行会不会产生额外结果。它们能一起用于下单,但解决的问题不同。原子性也不等于“绝不会同时出错”:两个人同时抢最后一件库存,还得考虑并发控制,才能判断谁可以下单。
什么时候用
适合用
- 做电商下单时,创建订单和扣减同库库存必须一起成功,否则会出现卖出数量与库存记录对不上的情况。
- 在后台转移账户余额时,转出方扣款和转入方加款都写入同一数据库,需要避免只完成一边。
- 用户兑换积分奖励时,扣积分和生成兑换记录属于同一笔操作,需要避免扣了积分却没有记录。
不适合用
- 用户在设置页单独修改头像昵称,没有必须一起完成的其他写入;做普通的数据更新就够了。
- 批量导入商品时,产品允许有效行先入库、错误行单独报告;逐行处理并返回结果,比整批失败更合适。
- 订单完成后给用户发邮件,邮件服务不受数据库事务控制;用可靠的异步任务处理发送,不把它当成同一组可回滚操作。
练一练选一个答案,看看解释
你在做下单接口:订单记录和库存记录在同一个数据库,还要发送确认邮件。怎样设计,才能避免留下有订单却没扣库存的数据?
让 AI 帮你做复制给 AI Agent 直接用
请为下单接口实现原子性:创建订单和扣减库存位于同一数据库事务中,任一步失败都不留下部分写入。确认邮件不纳入事务;请说明提交后如何安排发送,以及发送失败时如何处理。