MySQL字符集那些事儿,教你怎么避免乱码烦恼其实没那么难
- 问答
- 2026-01-18 11:58:28
- 2
你是不是也遇到过这种情况?明明在网页表单里输入的是好好的中文,存到MySQL数据库里再拿出来一看,就变成了一堆问号“???”或者像“åæ¶”这样的火星文,这种乱码问题,确实让人头疼,但说实话,只要你理解了MySQL字符集是怎么一回事,并且从一开始就做好正确的设置,避免乱码其实一点都不难,今天咱们就把它彻底讲明白。
咱们得知道乱码是怎么产生的,编码”和“解码”用的“字典”不一致,想象一下,你(中国人)用《新华字典》(UTF-8编码)写了一张纸条,上面写着“你好”,然后你把纸条交给一个朋友,他却以为这张纸条是用《英汉大词典》(比如Latin1编码)写的,然后他用那本词典去查你写的字,结果查出来的意思自然是驴唇不对马嘴,显示出来就成了乱码,这个过程中,任何一个环节用错了“字典”,乱码就会出现。
在MySQL的世界里,这个“字典”就是字符集(Character Set),而这个过程涉及到好几个环节,每个环节都有自己的字符集设置,根据MySQL官方文档(参考MySQL 8.0 Reference Manual, Chapter 10, Character Sets, Collations, Unicode)的描述,主要包含以下几个层面:
- 服务器层(Server Level):这是MySQL服务整体的默认字符集,你安装MySQL的时候可能会让你选,如果没选,它可能默认是
latin1,这个字符集对中文支持很不好。 - 数据库层(Database Level):在创建数据库的时候,可以指定这个数据库的默认字符集,如果没指定,就会用服务器层的设置。
- 数据表层(Table Level):创建表的时候,可以指定这张表的默认字符集,如果没指定,就用数据库的设置。
- 列层(Column Level):最精细的控制,可以为表里的某一个字段(比如
varchar,text类型的列)单独设置字符集,如果没指定,就用表的设置。 - 连接层(Connection Level):这个非常重要!指的是你的应用程序(比如PHP、Java程序)连接到MySQL数据库时,这次连接所使用的字符集,如果这里设置不对,哪怕前面都对了,数据在传输过程中也会“变味”。
你看,环节这么多,只要有一处没对上,乱码就找上门了,最省心、一劳永逸的办法是什么呢?就是统一天下,全部使用UTF-8。
UTF-8是一种非常强大的字符集,它几乎包含了世界上所有语言的字符,包括中文、日文、韩文、emoji表情等等,我们的目标就是把上面提到的所有环节,都设置为UTF-8家族的一员,在MySQL中,更准确的写法是utf8mb4。
为什么是utf8mb4而不是utf8呢?这里有个历史小知识,MySQL早期实现的utf8字符集其实是个“阉割版”,它最多只支持3个字节的字符,而真正的UTF-8是支持4个字节的,这就导致它无法存储像emoji表情这样的字符(emoji需要4个字节),会再次出现乱码,MySQL后来引入了真正的“完全体”utf8mb4字符集,现在基本上所有新项目都应该直接使用utf8mb4,你可以认为utf8mb4才是真正的UTF-8。
好了,理论说完了,具体怎么操作呢?咱们一步一步来。
第一步:检查当前的字符集设置。
你可以登录MySQL,用一些命令来看看现在是什么情况。
查看服务器和数据库的字符集:
SHOW VARIABLES LIKE 'character_set_server%'; SHOW VARIABLES LIKE 'character_set_database%';
查看连接的字符集相关设置(这几个非常关键):
SHOW VARIABLES LIKE 'char%';
你会看到像character_set_client(客户端用什么编码发数据)、character_set_connection(连接层转换用的编码)、character_set_results(结果集用什么编码返回给客户端)这些变量,理想情况下,它们都应该是utf8mb4。
第二步:如何设置和修改。

最佳实践:在创建数据库和表的时候,就明确指定。
创建数据库:
CREATE DATABASE my_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
这里的COLLATE叫做“排序规则”,它决定字符串比较和排序的顺序,utf8mb4_unicode_ci是一个通用的、不区分大小写的规则,一般用它就行。
创建表:
CREATE TABLE my_table (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
对于已经存在的数据库和表,也可以修改,但修改前一定要备份好数据!
修改数据库的字符集:
ALTER DATABASE my_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
修改表的字符集(注意:这只影响后续新增的列,原有列的字符集不会变):

ALTER TABLE my_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
这个CONVERT TO命令会同时转换表中所有列的字符集并重新存储数据,所以对于大表来说可能会很慢。
第三步,也是最容易忽略的一步:确保你的应用程序连接时也使用了正确的字符集。
以最常见的PHP为例,在通过mysqli连接数据库后,立刻执行一条设置语句:
$mysqli->set_charset("utf8mb4");
或者用PDO的话,可以在连接字符串里指定:
$pdo = new PDO("mysql:host=localhost;dbname=my_database;charset=utf8mb4", $username, $password);
对于Java + JDBC,可以在连接URL里加上参数:
jdbc:mysql://localhost:3306/my_database?characterEncoding=utf8&useUnicode=true
(注意:JDBC驱动中通常参数名是characterEncoding=utf8,它一般就指代utf8mb4)
你的网页文件本身也应该是UTF-8编码的。
在HTML的<head>部分,加入meta标签:
<meta charset="UTF-8">
避免MySQL乱码的黄金法则就是:从源头到终点,全线统一使用utf8mb4字符集,这包括你的操作系统文件编码、你的编辑器和IDE的编码、你的网页编码、你的应用程序连接MySQL时的编码设置,以及MySQL自身从服务器到列的所有层的编码设置。
只要你把这几个环节都检查一遍,确保它们都是“utf8mb4”阵营的,那么乱码这个烦恼,就真的会离你远去了,希望这篇内容能帮你彻底解决这个问题!
本文由称怜于2026-01-18发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/83022.html
