MySQL 中文乱码的解决方法

MySQL 里的中文变成了 ???,或者在 phpMyAdmin、Navicat 中显示为 我们?通常是表、连接和导入文件的字符集不一致。导出文件中的乱码可以在上面直接修复,再把 MySQL 统一设为 utf8mb4,以后就不会再出现。

支持文本和以下文件:

  • CSV
  • TXT
  • JSON
  • XML
  • SRT
  • VTT
  • TSV
  • MD
  • HTML
  • SQL
  • LOG

例如 Excel 导出、数据库备份、字幕或网站代码。

修复

  1. 拖入文件或粘贴文本
  2. 自动修复
  3. 复制或下载
或把文件拖到这里
  • 无需上传。 文件直接在浏览器中修复,不会离开你的设备。

  • 服务器位于欧盟。 Mojibuster 运行在 芬兰(欧盟)的服务器上,受《通用数据保护条例》(GDPR)约束。 GDPR 全文(EUR-Lex,英文)

MySQL 有三处需要设置字符集

  • 表和字段:数据以哪种字符集保存,例如 utf8mb4 或 latin1。MySQL 5.7 及更早版本的默认值是 latin1,存不下中文。
  • 连接:客户端和服务器之间用哪种字符集通信,用 SET NAMES utf8mb4 或连接参数设置。
  • 文件:导入或导出时文件的编码,在 phpMyAdmin 的导入页面中可以选择文件的字符集。

三处不一致,中文就会出错。最常见的有两种情况:

  • ???:字段或连接是 latin1,存不下中文,MySQL 把每个字都换成了 ?。这些文字已经丢失,只能从原始数据重新导入。
  • 我们:UTF-8 的中文经由 latin1 连接写进了 latin1 字段。在程序里看起来一切正常,phpMyAdmin 和导出文件里却是乱码。这种情况下字节还在,可以修复。
phpMyAdmin 导出的 CSV 中的一行

乱码

"1","张伟","北京市","13800138000"

修复后

"1","张伟","北京市","13800138000"

在 Windows 命令行中连接时

在简体中文 Windows 的 cmd 或 PowerShell 中运行 mysql 客户端时,控制台用的是 GBK(代码页 936)。即使数据库里的数据完全正确,查询结果也可能显示成 浣犲ソ 这样的乱码。这只是显示问题:先执行 chcp 65001 把控制台切换为 UTF-8,或用 mysql --default-character-set=gbk 让这次会话按 GBK 输出。不要为了让控制台显示正常而去改表的字符集。控制台的更多设置见 PowerShell 中文乱码。

检查字符集

  • SHOW VARIABLES LIKE 'character_set%'; 查看服务器和连接的设置。
  • SHOW CREATE TABLE users; 查看表和各个字段的字符集。
  • SELECT name, HEX(name) FROM users LIMIT 5; 查看实际保存的字节:在 utf8mb4 字段中,E4B8AD 是“中”,而 C3A4C2B8C2AD 则是已经乱码的“中”。

修复导出文件

  1. 在 phpMyAdmin 中把表导出为 SQL 或 CSV,或者使用 mysqldump --default-character-set=utf8mb4。
  2. 把文件拖到上面的框中。Mojibuster 只修复乱码的部分,正常的中文保持不变。
  3. 在 改动了什么? 中确认修复的位置,然后下载文件。
  4. 导入到字符集为 utf8mb4 的表中,导入时文件字符集选择 utf-8。
  5. 先在副本上测试,再替换正式的表。

导出文件始终不会离开你的电脑,含有客户信息也可以放心处理。导出的 CSV 用 Excel 打开出现乱码时,请看 Excel 打开 CSV 乱码。

从根本上解决

  • 新建表时指定 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci。
  • 程序的连接也要设为 utf8mb4,例如在 PHP 的 PDO DSN 中加上 charset=utf8mb4,在 JDBC 连接串中加上 characterEncoding=UTF-8。
  • 如果 latin1 字段里存的是 UTF-8 字节,不要直接用 CONVERT TO 转换,否则会再编码一次,变成双重乱码。安全的做法是先改为二进制类型:MODIFY name VARBINARY(255),再 MODIFY name VARCHAR(255) CHARACTER SET utf8mb4。
  • 不要使用 MySQL 的 utf8:它每个字符最多只存 3 个字节,保存 emoji 和部分生僻字时会报 Incorrect string value 错误。

常见问题

为什么程序里显示正常,phpMyAdmin 里却是乱码?

因为程序和数据库把同一个错误犯了两次:程序通过 latin1 连接写入 UTF-8,又用同样的方式读回来,所以看起来正常。phpMyAdmin 的连接是正确的,显示的才是真正保存的内容。

变成 ??? 的中文还能恢复吗?

不能。MySQL 在保存时就把存不下的字换成了 ?,原来的文字已经不在数据库里了。Mojibuster 也无法恢复,请从原始文件或备份重新导入。

MariaDB 也一样吗?

一样。MariaDB 的字符集设置和 MySQL 相同,命令也一样。

导出文件可以多大?

每个文件最大 100 MB。较大的数据库建议按表分别导出。

更多指南