根本原因是备份时未指定--default-character-set,导致mysqldump默认用latin1读取utf8mb4数据造成双重编码,sql文件中中文和emoji在备份那一刻已损坏;恢复时必须用mysql --default-character-set=utf8mb4导入,并确保文件开头有set names utf8mb4。

备份时没加 --default-character-set,恢复必然乱码
根本问题不在还原命令,而在备份那一刻:mysqldump 默认用 latin1 读取表结构和数据,即使库是 utf8mb4,只要没显式指定编码,导出的 SQL 文件里中文和 Emoji 就已损坏。文件开头若没有 SET NAMES utf8mb4; 或类似语句,基本可判定 dump 时漏了参数。
检查方法:
- 用
file -i backup.sql(Linux/macOS)或 VS Code 底部编码提示看实际文件编码 - 执行
head -n 5 backup.sql查看前几行是否有SET NAMES声明 - 运行
SHOW CREATE DATABASE db_name;确认原库确实是utf8mb4
mysql 命令行还原必须带 --default-character-set=utf8mb4
还原不是“把文件塞进去”,而是 MySQL 客户端要先解码 SQL 文本。不指定 --default-character-set,客户端就按编译默认值(通常是 latin1)解析,4 字节的 Emoji 直接被截断或错解为乱码。
正确写法:
mysql --default-character-set=utf8mb4 -u root -p db_name <p>错误写法(常见但无效):</p> <pre class="brush:php;toolbar:false;">mysql -u root -p db_name <p>注意:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2334" title="MySQL"><img src="https://img.php.cn/upload/skill/000/000/081/178900927846657.jpg" alt="MySQL" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="overflowclass">MySQL</a> <p class="overflowclass">编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。</p> </div> <a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
- 如果报
Unknown character set: 'utf8mb4',说明本地mysql客户端版本太老(utf8(不推荐,Emoji 仍会失败) - Windows 下别用 cmd,它默认代码页是 GBK,可能在读取文件时二次污染;改用 Git Bash 或 PowerShell
Navicat / 客户端显示 Emoji 为问号,不是数据问题
数据本身可能是完好的,只是客户端和服务端通信时字符集没对齐。MySQL 有三个关键变量控制交互:character_set_client、character_set_connection、character_set_results。只要其中任一环节是 utf8 或 latin1,Emoji 就会变成 ?。
验证与修复步骤:
- 连接后立即执行
SET NAMES utf8mb4;,再查数据 - 在 Navicat 连接属性 → 高级 → 「初始化命令」里填入
SET NAMES utf8mb4; - 检查服务端是否设置了
init_connect = 'set names utf8mb4'(见my.cnf的[mysqld]段)
备份文件缺 SET NAMES 且无法重备?手动补一句再还原
有些老旧脚本导出的 SQL 只含建表语句,无连接初始化,此时单靠 --default-character-set 不够——CREATE TABLE 中的 CHARACTER SET 子句可能被忽略,字段级编码仍错。
应急做法(仅限无法重做备份时):
- 用文本编辑器在
backup.sql最开头插入一行:SET NAMES utf8mb4; - 确保该行在任何
CREATE DATABASE或USE之前 - 再用带
--default-character-set=utf8mb4的命令还原
真正可靠的做法,是今后所有 mysqldump 都强制带上 --default-character-set=utf8mb4,并确认输出文件头部有 SET NAMES ——否则备份即失效,和加密没设密钥一样,还原只是徒劳。










