MySQL备份失败主因是服务端未启用utf8mb4,需在my.cnf中配置character-set-server=utf8mb4并重启,再用mysqldump --default-character-set=utf8mb4导出,确保SQL文件头为SET NAMES utf8mb4。
确认 MySQL 服务端已启用 utf8mb4
很多备份失败的根源不在 mysqldump,而在服务端压根没开 utf8mb4 支持。即使客户端设对了,服务端仍可能用 latin1 或 utf8(即 utf8mb3)做默认字符集,导致多语种字段(如 emoji、阿拉伯文、越南文、藏文)在写入时就被截断或转成 ?。
检查方式:
mysql -u root -e "SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';"重点关注
character_set_server 和 collation_server 是否为 utf8mb4 和 utf8mb4_0900_ai_ci(MySQL 8.0+)或 utf8mb4_unicode_ci(5.7)。如果不是,仅改客户端参数或 dump 命令无意义。
- 修改
my.cnf(Linux)或my.ini(Windows),在[mysqld]下加:character-set-server = utf8mb4\ncollation-server = utf8mb4_unicode_ci
- 重启 MySQL 服务后,重新建库/表才生效;已有表需单独
ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 注意:MySQL 5.7 默认
utf8是阉割版,不支持 4 字节 UTF-8 字符;utf8mb4才是真· UTF-8
mysqldump 必须显式指定字符集参数
即使服务端已设 utf8mb4,mysqldump 默认仍可能用 latin1 连接,尤其在未配 ~/.my.cnf 或命令行未传参时。这时 dump 出的 SQL 文件里中文、emoji 看似正常,但导入时会批量变 ?。
正确做法是强制连接层和导出层都走 utf8mb4:
- 导出命令必须带:
mysqldump --default-character-set=utf8mb4 -u user -p database_name > backup.sql
- 不能只写
--charset=utf8mb4—— 这个参数在部分旧版 mysqldump 中无效,--default-character-set才是实际生效的连接字符集开关 - 如果数据库名、表名含非 ASCII 字符(如中文库名),还需加
--skip-extended-insert避免某些客户端解析错行(虽少见,但混合语种环境建议加上)
检查 .sql 文件头是否含正确的 SET NAMES
dump 文件开头几行决定导入时的会话字符集。若看到 SET NAMES utf8 或 SET NAMES latin1,说明 dump 参数没生效,后续所有 INSERT 都按错误编码解析。
打开 backup.sql,搜索前 20 行,确认存在且仅有一行:
SET NAMES utf8mb4;
- 如果出现
SET NAMES utf8,立刻重跑 dump,确认用了--default-character-set=utf8mb4 - 如果文件里有多个
SET NAMES(比如中间某段又切回 utf8),说明源库触发了动态字符集切换,属于异常行为,应排查应用层是否执行了SET NAMES语句 - 导入前可手动替换,但治标不治本;真正可靠的是从 dump 源头卡死
导入时同样要指定 utf8mb4,且避免 source 命令陷阱
用 mysql 命令导入时,很多人直接 mysql -u user -p db ,以为“既然 dump 对了,导入就稳了”——但这里有个隐性坑:shell 重定向不经过 mysql 客户端的字符集协商,完全依赖文件本身开头的 <code>SET NAMES。
更稳妥的方式是进 mysql shell 后用 source,但必须先确保当前连接就是 utf8mb4:
- 先连库:
mysql --default-character-set=utf8mb4 -u user -p database_name
- 再执行:
source /path/to/backup.sql;
- 如果报
ERROR 1366 (HY000): Incorrect string value,大概率是某张表的列定义仍是utf8(不是utf8mb4),需先SHOW CREATE TABLE table_name查看,再ALTER TABLE ... MODIFY column_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
最易被忽略的一点:表结构里的 CHARACTER SET 和 COLLATE 是独立于连接层的硬约束。就算 dump 和导入全程 utf8mb4,只要某个 VARCHAR 列定义还是 CHARACTER SET utf8,存 emoji 就必然失败。










