订单可正常下单,创建 Shipment 时却提示无法从 Source 扣减,或发货成功但物理库存没变化。MSI 下单先写 reservation,实际 Source quantity 通常在发货时扣减;Source 选择和 Shipment 项必须一致。
固定复现条件
记录订单、Shipment、Source Code、SKU、发货数量、Source Item 数量和 reservation 累计值。确认是后台选择 Source、SSA 自动选择还是 ERP API 创建 Shipment。
SELECT source_code,sku,quantity,status FROM inventory_source_item WHERE sku='SKU-1';
SELECT sku,SUM(quantity) reserved FROM inventory_reservation WHERE sku='SKU-1' GROUP BY sku;
SELECT stock_id,website_id FROM inventory_stock_sales_channel;
SELECT item_id,sku,qty_ordered,qty_shipped FROM sales_order_item WHERE order_id=123;
php bin/magento inventory:reservation:list-inconsistencies -r
根据证据定位
选中 Source 没有足够物理数量、SKU 在该 Source 禁用、ERP 已扣减后 Magento 再扣一次,都会失败。Shipment 已存在但重试事件再次触发时,需要用外部 ID 幂等。
修复与回滚
修正 Source 分配和同步顺序,通过标准 Shipment/Source Deduction 服务处理。历史差异先逐单核对,再使用官方补偿流程;不要直接 UPDATE inventory_source_item 或删除 reservation。
验收
多 Source 下单、部分发货、重复 ERP 回调、取消和退款全链路测试;Source quantity、reservation、salable quantity 与 Shipment 最终一致。
生产环境操作前的检查
处理“Magento 2 发货时报 Source Deduction 失败”前,先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 SELECT;写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、app/etc/env.php 配置摘要和实际流量节点。
php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status
命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复;涉及客户、支付、税费、库存或订单的变更,应先在脱敏数据副本验证。
建立可比较的排查记录
每次实验只改变一个变量,记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象;旧对象恢复而新对象仍能复现,说明根因尚未消除。
| 检查层 | 证据 | 通过标准 |
|---|---|---|
| 入口 | URL、状态码、请求 ID、节点 | 路由与协议一致 |
| 应用 | 异常堆栈、模块、作用域 | 无新异常且可重复 |
| 数据 | 主键、时间、关联行数 | 关系完整无重复副作用 |
| 业务 | 正常、失败与重试路径 | 最终状态一致 |
修复后的观察窗口
上线后至少观察一轮 Cron、队列和索引周期,并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏,确认错误率、响应时间和数据量稳定后及时关闭。

