同一批中文数据,测试库 utf8mb4_general_ci 排出来是 阿 波 次,生产库 utf8mb4_0900_ai_ci 排出来是 波 阿 次,分页对不上。乍看像缓存或者权限的锅,追下去往往不是。
SHOW VARIABLES LIKE 'collation_%'; SELECT nickname FROM users ORDER BY nickname COLLATE utf8mb4_0900_ai_ci LIMIT 20; ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
追下去是这么回事:不同 collation 的排序权重表不同,0900 系列按 Unicode 9.0 的规则排,general_ci 用的是更老的简化权重。中文在这些规则里都没有拼音顺序,结果自然不一致。
「utf8mb4 排序规则差异」这类改动最怕改一半,回滚脚本先准备好,再动生产。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
偶发问题先统计频率,一小时几次和一天一次,查法完全不同。改完顺手把文档补一句,省得下次自己重新推一遍。
监控和日志的时间要对上,时区不一致会多绕很大一圈。
具体做法是,两库统一成同一个 collation 用 0900_ai_ci;连接串和表定义都要改 只改一处仍会混排;需要拼音排序就显式用 CONVERT 加 gbk 或应用层排;改完对比同一查询的 ORDER BY 结果。
验收就看一点,两库同一查询返回顺序一致 分页不再出现重复或漏条。
