mysqldump 默认不导出数据库级字符集和排序规则,需用 --no-data --databases 显式导出含 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci 的 CREATE DATABASE 语句;PostgreSQL 的 lc_collate 和 encoding 由 initdb 决定,pg_dump 不包含,须记录原始集群参数并用相同 initdb 参数重建;MySQL 8.0 导出的 utf8mb4_0900_ai_ci 在 5.7 恢复会报 ERROR 1273,应升级目标库或降级 collation;Docker 中 mysqldump 依赖容器内配置,须显式指定 --default-character-set=utf8mb4 并验证 dump 文件头部 SET NAMES。
mysqldump 怎么导出字符集和排序规则
直接用 mysqldump 默认不保存数据库级别的 character set 和 collate,只导出表结构里的定义。如果目标库是空的、又没手动建库,恢复后库级字符集会退化成服务器默认值(比如 latin1),中文就乱码。
必须加 --default-character-set=utf8mb4 并配合 --skip-create-options 以外的选项——但更稳的方式是显式导出 CREATE DATABASE 语句:
-
mysqldump --no-data --databases mydb --skip-create-options > db_def.sql—— 这条会包含带CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci的CREATE DATABASE - 再用
mysqldump --no-create-db --no-create-info mydb > data.sql导出表与数据,避免重复建库语句 - 两个文件顺序执行:先跑
db_def.sql,再跑data.sql
PostgreSQL pg_dump 是否保留 lc_collate 和 encoding
pg_dump 默认导出的 SQL 文件里,CREATE DATABASE 语句不含 LC_COLLATE 或 ENCODING,因为这些是 initdb 阶段定死的,不能在 CREATE DATABASE 时覆盖。所以“备份字符集”对 PostgreSQL 来说,本质是备份集群初始化参数。
正确做法不是靠 dump 文件,而是记录原始集群信息:
- 运行
pg_controldata查Database cluster state和Encoding字段 - 查
SHOW lc_collate; SHOW lc_ctype;确认区域设置 - 用
pg_dumpall --globals-only备份角色和表空间,它不包含编码,但能帮你复现权限上下文
恢复时必须用相同 initdb -E UTF8 --lc-collate=C 参数重建集群,否则即使 dump 恢复成功,排序行为也会错位。
MySQL 恢复时字符集不一致导致的 ERROR 1273
错误信息 ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci' 很典型——源库是 MySQL 8.0+,目标库是 5.7 或更低版本。这个排序规则在 5.7 里不存在,dump 文件里又没做兼容降级。
解决路径只有两条:
- 升级目标 MySQL 到 8.0+(推荐)
- 导出时强制降级:加参数
--column-statistics=0 --set-gtid-purged=OFF --compatible=mysql40,并手动替换 dump 文件里的utf8mb4_0900_ai_ci为utf8mb4_general_ci(注意:后者已弃用,仅作临时过渡) - 别信
--skip-extended-insert能解决这个错——它只影响 INSERT 格式,跟 collation 无关
Docker 环境下 mysqldump 容器怎么读取宿主机字符集配置
容器里跑 mysqldump 时,它读的是容器内 my.cnf 或环境变量,不是宿主机 MySQL 的配置。容易误以为“连上去了就自动继承”,结果导出的建库语句还是用默认字符集。
安全做法是显式传参,而不是依赖配置文件:
- 用
docker run --rm mysql:8.0 mysqldump -h host.docker.internal -u root -p'xxx' --default-character-set=utf8mb4 --databases mydb - 避免挂载宿主机
/etc/mysql/my.cnf进容器——路径可能不匹配,且容器内 MySQL 客户端版本和配置格式未必兼容 - 如果要用配置文件,务必在容器内用
mysql --help | grep "Default options"确认实际加载路径,再docker cp进去
最易被忽略的一点:即使导出命令写了 --default-character-set,如果连接时用了 SET NAMES latin1(比如某些旧版客户端自动发),dump 内容仍可能被转码。检查 dump 文件头部是否有 SET NAMES utf8mb4,没有就说明连接层已失守。










