标准答案

  1. 执行 `UPDATE inventory SET stock = stock - ? WHERE sku = ? AND stock >= ?`。
  2. 影响行数为 1 才表示扣减成功;为 0 时区分库存不足、SKU 不存在或请求重复。
  3. 订单和扣减记录要使用唯一业务键,事务提交后再发布后续事件。

题目解析

条件 UPDATE 把“库存仍足够”和“扣减库存”放进数据库的同一个原子写操作,多个请求竞争时只有满足条件且成功更新的请求可以扣减,避免先 SELECT 再 UPDATE 的竞态。

影响行数为零不一定只代表库存不足,也可能是 SKU 不存在、请求重复或条件版本冲突。接口要结合库存记录、幂等记录和订单状态给出可解释结果。

扣减成功后要在同一事务中记录订单或扣减证据,并用 Outbox 或可恢复事件通知后续流程。缓存预扣只能削峰,不能替代权威库存和对账。

代码示例

SQL 核心:

sql
UPDATE inventory
SET stock = stock - :quantity, version = version + 1
WHERE sku = :sku AND stock >= :quantity;

常见误区

  • 误区:先 SELECT 再 UPDATE 不带条件。改正:使用带 stock >= quantity、版本或状态条件的原子更新。
  • 误区:失败统一返回成功。改正:区分库存不足、SKU 不存在、重复请求和系统故障,不要伪造订单成功。
  • 误区:扣库存成功但没有订单或事件证据。改正:在事务中记录扣减结果,并为后续事件提供 Outbox、重试和对账。

作者信息