mysql客户端连接默认字符集非utf8mb4,需在服务端配置、建表语句、连接参数及客户端环境等各环节统一设为utf8mb4,否则中文易出现问号或乱码。

MySQL客户端连接时默认字符集不是utf8mb4
MySQL 5.7+ 默认服务端字符集可能是 latin1 或 utf8(注意:不是 utf8mb4),而客户端(如命令行、Python的pymysql、Java的jdbc)若没显式指定,会继承服务端默认值或按自身规则 fallback,结果就是插入中文变问号或 Mojibake。
实操建议:
- 查当前连接字符集:
SHOW VARIABLES LIKE 'character_set%';和SHOW VARIABLES LIKE 'collation%';,重点关注character_set_client、character_set_connection、character_set_results - 临时修改当前会话:
SET NAMES utf8mb4;(等价于同时设 client/connection/results 为utf8mb4) - 永久生效需在配置文件(如
/etc/mysql/my.cnf)的[client]、[mysql]、[mysqld]三节下分别加:default-character-set = utf8mb4(client段)和character-set-server = utf8mb4(mysqld段) - 重启 MySQL 后验证:
mysql --defaults-file=/etc/mysql/my.cnf -u root -p -e "SHOW VARIABLES LIKE 'character_set%';"
建表时没指定字符集,沿用数据库默认值
即使数据库(CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;)设对了,新建表仍可能用错编码——因为表级字符集不显式声明时,会继承数据库默认值;但若数据库本身是 latin1,那表就还是乱码温床。
实操建议:
- 建表必须显式声明:
CREATE TABLE t (name VARCHAR(100)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - 已有表转换:
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;(注意:该操作会锁表,大数据量慎用) - 检查字段级字符集:
SHOW CREATE TABLE t;看每列是否都落在utf8mb4下;个别字段若被单独设成latin1,需单独改:ALTER TABLE t MODIFY COLUMN name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
应用程序连接字符串漏掉charset参数
很多 ORM 或驱动默认不发 SET NAMES,也不自动协商字符集。比如 Python 的 pymysql 不加 charset='utf8mb4' 参数,就会用 latin1 连接;Java 的 JDBC URL 若没写 ?characterEncoding=utf8mb4&serverTimezone=UTC,同样出问题。
实操建议:
pymysql.connect(..., charset='utf8mb4')- JDBC URL 示例:
jdbc:mysql://localhost:3306/db?characterEncoding=utf8mb4&serverTimezone=UTC&useUnicode=true - Node.js 的
mysql2配置:{ charset: 'UTF8MB4_GENERAL_CI' } - PHP PDO DSN 中加:
;charset=utf8mb4 - 重点:
charset参数值必须和 MySQL 服务端支持的校对名一致,utf8mb4是字符集名,不是校对名;校对名如utf8mb4_unicode_ci,但多数驱动只认charset值为utf8mb4
SELECT返回结果仍是乱码,但建表和连接都对了
最隐蔽的情况:SQL 语句里写了中文字符串字面量,但客户端发送前已损坏。例如终端 locale 是 C 或 POSIX,shell 输入的中文在传给 MySQL 前就转成了错误字节流;或者编辑器保存 SQL 文件用了 GBK 编码,而 MySQL 认为它是 utf8mb4 解析。
实操建议:
- Linux 终端确认:
locale | grep UTF,确保LANG是zh_CN.UTF-8类似值 - SQL 文件用 UTF-8 无 BOM 编码保存(VS Code / Sublime 都可设),执行前可用
file -i xxx.sql检查编码 - 避免在 SQL 里硬写中文,改用参数化查询(
INSERT INTO t VALUES (?);),把编码责任交给驱动处理 - 如果用
mysql命令行工具执行脚本,加--default-character-set=utf8mb4参数,否则它可能按本地 locale 推断编码
真正麻烦的从来不是改一个配置,而是每个环节——服务端、数据库、表、字段、连接、客户端环境、SQL 字面量——只要有一环没对齐,乱码就藏在某个你没想到的地方等着你。











