访客购物车已有商品,登录后同一 SKU 出现两行或数量翻倍。Magento 是否合并为同一行不只看 SKU,还比较自定义选项、可配置属性和 buy request;自定义登录流程重复调用 merge 也会把数量累加两次。

固定复现条件

保存登录前 guest quote、客户 active quote、登录后 quote_id 和每个 item 的 SKU、qty、parent_item_id、product_options。对个人数据脱敏,并区分真正重复与选项不同的合法两行。

SELECT entity_id,customer_id,is_active,items_count,items_qty,updated_at FROM quote WHERE entity_id IN (101,202,303);
SELECT item_id,quote_id,parent_item_id,sku,qty,product_type,product_options
FROM quote_item WHERE quote_id IN (101,202,303) ORDER BY quote_id,item_id;
grep -R --line-number 'merge(|mergeCart|assignCustomer' app/code 2>/dev/null

根据证据定位

选项完全相同但数量双倍,查 merge 被调用两次或并发登录;SKU 相同而 super_attribute/custom_options 不同,保留两行可能正确;guest quote 被错误重复激活也会产生多次合并。

修复与回滚

使用标准 Quote 合并流程,并以登录事务或请求标识保证幂等。自定义比较逻辑应包含影响购买结果的全部选项;不要在数据库中按 SKU 粗暴删除行,否则会丢失合法配置。

验收

测试空客户购物车、双方均有相同商品、不同选项、可配置与 Bundle,并发点击登录。最终数量与业务规则一致,优惠、库存和 totals 只计算一次。

生产环境操作前的检查

处理“Magento 2 登录后合并购物车出现重复商品”前,先记录 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 重复验证。临时调试日志必须脱敏,确认错误率、响应时间和数据量稳定后及时关闭。