这个问题表面看是父商品库存,实际几乎都要落到子SKU。可配置父商品没有独立的真实数量,它能不能卖取决于至少一个子商品在当前Stock下可售。后台“数量”正确,只能证明source_item有值,不能证明销售渠道使用的Stock能算出正的salable quantity。
先选一个确实应该可售的子SKU
bin/magento inventory:reservation:list-inconsistencies -r bin/magento inventory:reservation:create-compensations -r
上面两条不要盲目直接连着执行。先运行第一条保存输出,确认不一致记录对应的订单确实已经完成、取消或退款,再把确认过的结果交给补偿命令。生产环境建议先在数据库备份或从库中核对。
三个位置要同时看
1. Source Item
SELECT source_code,sku,quantity,status
FROM inventory_source_item
WHERE sku IN ('CHILD-SKU-1','CHILD-SKU-2');
quantity大于0但status=0时,商品仍不可售。CSV导入尤其容易只更新数量而漏掉状态。需要重新导入status=1,或通过SourceItemsSaveInterface更新,别直接长期用SQL改业务数据。
2. Stock与销售渠道映射
SELECT s.stock_id,s.name,sc.type,sc.code FROM inventory_stock s LEFT JOIN inventory_stock_sales_channel sc ON sc.stock_id=s.stock_id;
确认当前网站代码映射到预期Stock。如果网站还指向Default Stock,而数量被录入到只属于另一个Stock的Source,后台看起来有库存,前台仍会是0。
3. 预留数量
SELECT sku,SUM(quantity) AS reservation_total FROM inventory_reservation WHERE sku='CHILD-SKU-1' GROUP BY sku;
reservation是追加式流水,不应该删除某一行来“修库存”。如果订单状态流转曾被自定义插件中断,应创建相反数量的补偿记录,并修正那个状态流转插件,避免每天继续产生负数。
重新索引并验证当前Stock
bin/magento indexer:reindex inventory bin/magento cache:clean
不同版本的索引器名称可能显示为inventory或inventory_stock,先用 bin/magento indexer:info 确认。然后查询对应的 inventory_stock_<stock_id> 视图或表。
SELECT sku,quantity,is_salable
FROM inventory_stock_2
WHERE sku IN ('CHILD-SKU-1','CHILD-SKU-2');
- source_item数量和状态正确
- 网站映射到包含该Source的Stock
- reservation汇总符合订单实际
- inventory_stock_N中至少一个子SKU的is_salable=1
- 前台切换到该子商品组合后能加入购物车
如果这些都正确而父商品仍不可售,再检查自定义 salability condition、backorder配置和最小销售数量。排查顺序很重要:先把MSI基础数据链路走通,再看插件,不然很容易在父商品上反复改数量却没有任何效果。

