订单取消后,Source Item 的实际数量可能从未减少,但 Salable Quantity 仍少了下单数量。这是 MSI 中“物理数量”和“Reservation”没有对齐的典型现象。下单通常写负 reservation,取消应写对应的正补偿记录。
按订单号查询完整 Reservation 链
SELECT reservation_id, stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE metadata LIKE '%000000123%'
ORDER BY reservation_id;
同一 SKU 正常会看到负数下单记录和正数取消记录,两者合计为零。不要修改已有 reservation 行;它是追加式记录,直接 UPDATE 会破坏审计链。
SELECT sku, stock_id, SUM(quantity) AS reservation_total
FROM inventory_reservation
WHERE sku='ABC-001'
GROUP BY sku, stock_id;
SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku='ABC-001';
reservation_total 为负表示仍有未补偿预留,但还要确认订单是否存在其他有效占用。Source Item quantity 正常并不能证明可售数量正常。
让 Magento 找不一致,不手写补偿 SQL
bin/magento list inventory | grep reservation
bin/magento inventory:reservation:list-inconsistencies -r
bin/magento inventory:reservation:list-inconsistencies | bin/magento inventory:reservation:create-compensations
不同版本参数可能略有差异,先用 list 确认。生成补偿前保存命令输出并限定维护窗口;结果可能包含仍在处理的订单,不应看到列表就全部执行。
取消为何没生成正记录
- ERP 直接改了订单 state/status,没有调用 Magento 取消服务;
- 插件在取消事务中抛异常,库存消息未完成;
- 消息消费者停止,异步库存处理积压;
- 外部系统重复取消,幂等处理有缺口。
grep -Rni '000000123|ABC-001' var/log | tail -n 100
bin/magento queue:consumers:list | grep -i inventory
ps -ef | grep '[q]ueue:consumers:start'
补偿后重新查询 reservation 合计,并从前台执行加入购物车和下单预检。真正修复还应让 ERP 通过订单服务取消,而不是继续直接更新数据库。
先确认订单动作是真的 Cancel
后台的自定义状态名称可能叫“已取消”,但订单 state 仍是 processing 或 closed。查询 sales_order.state、status、total_canceled 和商品的 qty_canceled,确认业务系统调用的是取消服务而不是只改显示状态。只有真实取消事务才会触发库存补偿。

