CSV 里有两个相同邮箱,一个属于中国站,一个属于欧洲站。业务认为它们是两个独立账号,但导入到一半出现“重复邮箱”。这不是简单的数据清洗问题,因为 Magento 是否允许相同邮箱跨网站存在,由客户账号共享范围决定。

先确定你们的账号模型

php bin/magento config:show customer/account_share/scope

SELECT website_id, email, COUNT(*) AS cnt
FROM customer_entity
GROUP BY website_id, email
HAVING COUNT(*) > 1;

共享范围为 Global 时,一个邮箱在整个 Magento 实例只能对应一个客户;范围为 Per Website 时,相同邮箱可以分别存在于不同 Website。这里的边界是 Website,不是 Store View。

不要为了让导入通过就临时切换范围。已有客户、登录行为、地址、订单归属和第三方 SSO 都可能依赖当前模型。范围变更应当作为独立迁移项目评估。

“两个网站”可能只是两列写法不一致

客户导入文件需要把记录映射到真实 Website。不同 Magento 版本或导入模式使用的列名可能不同,后台示例文件是最可靠的起点。常见错误包括:

  • 填写了 Store View code,却以为是 Website code;
  • 一个 code 带了不可见空格或大小写不一致;
  • 目标环境的 Website code 与测试环境不同;
  • 更新模式下没有提供客户现有 website,系统尝试在默认网站创建;
  • CSV 中同一邮箱在同一 Website 本来就重复,只是行距很远。

导入前做一次规范化预检

我会把邮箱转为统一大小写、去掉首尾空格,再按“规范化邮箱 + 目标 website code”统计重复。与此同时,从目标环境导出现有客户的 entity_id、email 和 website_id 做冲突比对。这样能把三种情况分开:

  1. CSV 自己重复;
  2. CSV 与现有客户冲突;
  3. 网站映射失败后全部落到了默认 Website。

预检文件里不要散布真实客户邮箱。可以在受控环境处理,并在报告中使用哈希或遮罩。

看到重复记录时,别直接合并 customer_entity

两个客户可能各自拥有订单、地址、订阅、积分和外部系统 ID。即使邮箱相同,也不能仅凭这一字段判断是同一个人。先让业务确认账号共享策略和客户身份,再决定保留、迁移还是合并。

数据库唯一约束报错只说明当前键不允许插入,并不告诉你哪种业务处理正确。删除唯一索引会让脏数据进入系统,之后登录查询可能返回不确定的客户。

一个安全的重跑方法

先用 5 条小样本覆盖:新邮箱、目标网站已有邮箱、另一个网站同邮箱、未知 website code、带空格邮箱。选择与正式任务相同的 Add/Update 行为,核对导入报告后再扩大批次。正式重跑必须保证可幂等:已经成功的客户应被识别为更新或跳过,不能再创建一份。

最终不仅要看“导入成功多少条”,还要在两个 Website 分别测试登录、忘记密码、客户地址和历史订单可见性。账号范围问题最容易在导入时被绕过去,然后在客户登录时爆出来。