字符集不一致的乱码根源
mysqldump 的 --default-character-set 决定导出时连接的字符集,也决定产物中 SET NAMES 的取值。字符集不统一时会出现两种典型问题:产物字节按一种编码写出、恢复时按另一种编码解读,中文变成乱码;或者同一份数据在转码过程中被双重编码,恢复后内容已经变化。
基本信息
| 适用 | MySQL 5.7 / 8.0 的 mysqldump 与 mysql 客户端 |
|---|---|
| 核心选项 | --default-character-set=utf8mb4 |
| 为什么重要 | 连接字符集决定导出与导入时的字节编码 |
| 检查方式 | 查看产物头部的 SET NAMES 语句 |
指定字符集导出与导入
指定字符集导出与导入
mysqldump -uroot -p --default-character-set=utf8mb4 --single-transaction --databases appdb > appdb.sql # 导出时显式声明字符集
head -20 appdb.sql | grep -i "SET NAMES" # 确认产物声明的字符集
file -i appdb.sql # 查看文件编码,辅助判断是否异常
mysql -uroot -p --default-character-set=utf8mb4 appdb < appdb.sql # 导入端也要匹配字符集
mysql -uroot -p -e "SHOW VARIABLES LIKE 'character_set%';" # 核对服务端字符集设置判据与常见组合
| 场景 | 表现 | 处理 |
|---|---|---|
| 源库 utf8mb4,导出未指定字符集 | 中文乱码或问号 | 导出与导入都显式指定 utf8mb4 |
| 源库 latin1,按 utf8mb4 导出 | 双重编码,乱码且不可逆 | 按源库实际字符集导出后再转换 |
| 导入端字符集不匹配 | 写入后显示异常 | mysql 命令同样加 --default-character-set |
| 产物头部 SET NAMES 与预期不符 | 恢复后编码错位 | 以产物声明的字符集为准导入 |
| 跨版本迁移 | 排序规则不被识别 | 检查目标版本是否支持该 collation |
典型使用场景
- 跨环境迁移备份,保证中文与特殊字符不乱码
- 老库从 latin1 迁到 utf8mb4 时的编码核对
- 排查恢复后中文乱码,确认导出与导入两侧字符集
- 备份产物交付前的自检,确认 SET NAMES 正确
- 跨版本升级备份,兼顾排序规则兼容性
导出与导入必须成对处理字符集:只改一侧往往会用错误编码解读正确字节,产生的乱码通常不可逆。
源库使用 latin1 而导出时按 utf8mb4 处理,会把字节再转码一次形成双重编码,恢复后的中文基本无法还原,务必先确认源库实际字符集。