直接改SQL文件里的utf8mb4_0900_ai_ci不够,必须同步替换表级、列级及CREATE DATABASE语句中的所有该排序规则为utf8mb4_general_ci;不能将utf8mb4字符集降级为utf8,否则会丢失emoji等4字节字符支持。

直接改SQL文件里的utf8mb4_0900_ai_ci就行吗?
不行,只替换utf8mb4_0900_ai_ci为utf8mb4_general_ci看似简单,但容易漏掉三类地方:表级COLLATE、列级COLLATE、以及CREATE DATABASE语句中的默认排序规则。MySQL 5.7不认识utf8mb4_0900_ai_ci,但认识utf8mb4_general_ci——前提是所有层级都统一替换,否则导入中途就会报错中断。
实操建议:
- 用
grep -n "utf8mb4_0900_ai_ci" your_dump.sql定位全部出现位置,别依赖编辑器“全文件替换”功能,有些可能藏在注释或长字符串里 - 优先处理
CREATE TABLE语句末尾的COLLATE=utf8mb4_0900_ai_ci,再查每个VARCHAR列定义后的COLLATE子句 - 如果导出时用了
--skip-set-charset,则SET NAMES语句里也可能含该排序规则,需一并替换
为什么不能把utf8mb4全替成utf8?
因为utf8在MySQL里是阉割版:最多只支持3字节Unicode字符(如基本汉字、拉丁字母),不支持emoji、部分生僻中文、数学符号等4字节字符。而utf8mb4才是完整UTF-8实现。盲目替换成utf8,后续插入4字节字符会截断或报错Incorrect string value。
正确做法是保留utf8mb4字符集,只换排序规则:
-
utf8mb4_0900_ai_ci→utf8mb4_general_ci(兼容性最好,5.7原生支持) - 或→
utf8mb4_unicode_ci(排序更准,但5.7需确认是否启用innodb_large_prefix=ON) - 避免用
utf8_general_ci,它对应的是utf8字符集,不是utf8mb4
mysqldump导出时怎么避免这个问题?
下次从8.0导出给5.7用,别用默认参数。关键就两个选项:
- 加
--compatible=mysql57:自动降级语法+排序规则,但注意它不会改utf8mb4_0900_ai_ci,只是让其他语法兼容 - 必须显式指定
--default-character-set=utf8mb4 --collation-server=utf8mb4_general_ci,再配合--skip-set-charset防止导出文件里写死8.0专属排序规则 - 如果表已存在,导出前先在8.0里执行
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,这样导出内容天然兼容
应用连接层要不要同步调整?
要。即使SQL文件修复了,应用连上去后若没指定排序规则,MySQL仍可能按服务端默认值分配,导致ORDER BY结果不一致或索引失效。
检查并统一以下三处:
- 连接URL里加上
?characterEncoding=utf8mb4&collation=utf8mb4_general_ci(JDBC) - 初始化SQL中执行
SET NAMES utf8mb4 COLLATE utf8mb4_general_ci - 确认
my.cnf里[client]和[mysqld]段的collation-server设为utf8mb4_general_ci,重启生效
最易忽略的是连接池预编译语句缓存——旧连接可能还带着8.0的排序上下文,上线后首次查询异常,得清空连接池或重启应用。


















