管理员删除一个颜色选项后,部分商品保存报错,或者前台筛选出现空白项。这通常不是缓存问题,而是某处仍保存着已经不存在的 option_id。Magento 的属性定义、选项、商品值和可配置商品关系分布在不同表中,必须先确认引用链。

确定属性和后端值表

SELECT attribute_id, attribute_code, backend_type, frontend_input
FROM eav_attribute
WHERE attribute_code = 'color';

单选 select 常见 backend_type 为 int,对应 catalog_product_entity_int;多选通常存为 varchar 中的逗号分隔值。不要假定所有选项属性都在 int 表。

查找已经没有定义的值

对于 int 类型,可先做只读查询:

SELECT v.entity_id, v.store_id, v.value AS option_id
FROM catalog_product_entity_int AS v
LEFT JOIN eav_attribute_option AS o ON o.option_id = v.value
WHERE v.attribute_id = 93
  AND v.value IS NOT NULL
  AND o.option_id IS NULL;

把 93 换成实际 attribute_id。多选属性不能直接等值 join,需要在应用层拆分每个 option_id,或在副本上用受控 SQL 检查。用 LIKE '%12%' 会把 12、112、120 混在一起,不适合清理。

可配置商品还要查 super attribute

若该属性用于 configurable product,确认配置属性记录和子商品组合是否仍有效。删除一个选项不等于应该删除子商品;很多时候应给商品改成新的选项值,并同步外部 ERP 映射。

先导出受影响 entity_id、SKU、store_id、旧值,和业务负责人确认替代方案。直接删除 EAV 行会使商品回退到默认范围或空值,可能改变前台可见性、分层导航和变体选择。

为什么保存时才暴露

旧数据可能一直能被读取,但商品保存会重新运行属性验证、扩展 plugin 或搜索索引更新,于是抛出 “option not found”。查看完整堆栈,区分核心属性验证与第三方映射表报错。若扩展自己保存 option_id,还要一起迁移。

安全修复顺序

在测试环境还原同一商品;为孤立值建立旧值到新值的映射;通过 repository/批量导入更新商品;确认可配置组合、筛选和搜索正常;最后才移除不再需要的残留关系并重建相关索引。所有修改前备份目标行,生产 SQL 要限定 attribute_id、entity_id 与 store_id。修复后重新保存一个受影响商品,验证错误确实不再出现,而不是仅靠全量索引隐藏空白选项。