INSERT INTO user_phone_map(phone, user_id) VALUES ('13800138000', 88123);
-- 唯一键冲突即视为重复注册

用户表按 id 分片,phone 上建了唯一索引,同一手机号在两个片各注册成功一次,登录时随机命中其中一个账号。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:唯一索引只在单个分片内生效,两个片的索引互不可见。手机号不是分片键,插入时路由到哪片由 id 决定,重复值自然落不到一起。

「跨片唯一约束」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。同一份配置存在多处的,先确认改的是被加载的那一份。

新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。

处理上按这个顺序:把需要唯一的字段作为分片键 或者单独建映射表;用一张 phone 到 user_id 的全局表 插入前先占位;占位表加唯一索引 冲突直接返回已注册;存量重复数据合并 保留最早注册的那个。

确认没问题再收工,同一手机号第二次注册返回已存在 两个片不再各存一条。

作者 9823189