最稳妥方法是仅替换 collation 为 utf8mb4_unicode_ci,保留 charset utf8mb4,避免改 charset 导致丢数据;需覆盖建库、建表、字段三处 collation,并用 grep 确认清理干净。

直接替换 utf8mb4_0900_ai_ci 为兼容版本(如 utf8mb4_unicode_ci)是最稳妥、最常用的方法,不会丢数据,但会影响排序和比较行为——比如 'café' 和 'cafe' 在 WHERE 或 ORDER BY 中可能不再等价。
为什么不能只替换 collation 而不碰 charset
因为 utf8mb4 字符集本身在 MySQL 5.7 中完全支持,真正不被识别的是 utf8mb4_0900_ai_ci 这个排序规则名。硬把 utf8mb4 改成 utf8 是危险操作:utf8 在 MySQL 里是阉割版,最多存 3 字节字符,会丢 emoji、生僻汉字甚至部分数学符号,后续插入直接失败或乱码。
正确做法是保留 CHARACTER SET utf8mb4,只降级 COLLATE:
-
utf8mb4_0900_ai_ci→utf8mb4_unicode_ci(推荐,5.7 原生支持,语义最接近) -
utf8mb4_0900_as_cs→utf8mb4_bin(大小写敏感场景的 fallback) - 避免用
utf8mb4_general_ci(MySQL 5.7 虽支持,但已弃用,排序准确性较差)
sed 批量替换时容易漏掉的三类位置
只搜一次 utf8mb4_0900_ai_ci 很可能漏掉关键位置,必须覆盖全部三种写法:
- 建库语句:
CREATE DATABASE `xxx` DEFAULT COLLATE=utf8mb4_0900_ai_ci - 建表语句末尾:
ENGINE=InnoDB DEFAULT COLLATE=utf8mb4_0900_ai_ci - 字段定义中:
name VARCHAR(255) COLLATE utf8mb4_0900_ai_ci
Linux/macOS 推荐命令(一行搞定):
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g; s/DEFAULT COLLATE=utf8mb4_0900_ai_ci/DEFAULT COLLATE=utf8mb4_unicode_ci/g' dump.sql
Windows PowerShell 替代方案:
(Get-Content dump.sql) -replace 'utf8mb4_0900_ai_ci', 'utf8mb4_unicode_ci' | Set-Content dump.sql
mysqldump 导出时就该避开这个坑
等导入报错再修 SQL 文件,不如导出时就切掉隐患。用 mysqldump 时加这两个参数:
-
--compatible=mysql57:强制让 dump 工具“装作”自己是 5.7 版本,不输出新 collation -
--skip-set-charset:禁用SET NAMES语句,避免头部出现COLLATE utf8mb4_0900_ai_ci
完整命令示例:
mysqldump --compatible=mysql57 --skip-set-charset -u root -p database_name > dump.sql
如果用 Navicat,导出前进「高级」选项卡,勾选 Use compatible mode 并指定 MySQL 5.7;同时取消勾选 Include character set and collation。
真正容易被忽略的是:有些 SQL 文件里 COLLATE 出现在注释块内、多行定义中,或被引号包裹(如字符串值),sed 默认不处理。建议替换后用 grep -n "utf8mb4_0900_ai_ci" dump.sql 确认是否清零,再执行导入。











