后台 Source Quantity 是 20,前台可售数量却是 14;或者订单取消后库存没有回来。MSI 的 Salable Quantity 不是简单等于 Source Quantity,它还会叠加对应 Stock 的 reservation。修复时应追加补偿 reservation,不能删除表记录。
先记录 SKU、Website 与 Stock
bin/magento inventory:reservation:list-inconsistencies
数据量大时不要把输出直接在终端滚完,可以先限制到订单范围:
bin/magento inventory:reservation:list-inconsistencies -r 000001200-000001500
不同版本命令参数可能略有差异,先运行 --help 确认。输出中的订单号、SKU、补偿数量和 Stock ID 是后续审核依据。
拿一条结果手工核算
SELECT stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE sku = 'SKU-001'
ORDER BY reservation_id;
SELECT sku, source_code, quantity, status
FROM inventory_source_item
WHERE sku = 'SKU-001';
reservation 正数和负数代表对可售量的增减,不能只数行数。打开 metadata 中的 order increment ID 和 event type,对照订单的下单、取消、发货或退款时间。若订单仍在正常处理中,负 reservation 可能完全合法。
把 CLI 输出先保存为审核文件
bin/magento inventory:reservation:list-inconsistencies -r 000001200-000001500 > /tmp/reservation-fix.txt
sed -n '1,40p' /tmp/reservation-fix.txt
wc -l /tmp/reservation-fix.txt
逐条排除正在处理、外部 ERP 尚未回写或业务人员正在操作的订单。高峰期库存还在变化,诊断与执行之间的窗口越长,越容易把新状态当成旧差异。
确认无误后通过管道创建补偿
bin/magento inventory:reservation:list-inconsistencies -r 000001200-000001500 | bin/magento inventory:reservation:create-compensations
先在预发布和一个很小的订单范围验证。生产执行前备份数据库,并暂停会同时修改相关订单/库存的集成任务。该命令应该新增补偿记录,而不是改写历史;历史 reservation 是审计链。
补偿以后不要只看后台 Grid
bin/magento indexer:status
bin/magento indexer:reindex inventory
bin/magento cache:clean
实际 indexer 名称按版本的 indexer:info 为准。随后重新运行 list-inconsistencies,原结果应消失;再用商品页、GraphQL/REST 可售查询和一次测试下单确认。
差异为什么会反复出现
常见根因不是索引,而是旧版本升级时缺少初始补偿、订单导入绕过标准服务、状态回滚失败、第三方模块直接改订单状态,或消费者/Cron 没有完成异步库存动作。根据 metadata 的 event type 和故障时间定位源头;否则今天补平,下一批订单还会继续产生差异。

