insert 出现 \xe6\x88\x91 错误是因客户端、连接层、表字段未统一配置为 utf8mb4;mysql 的 utf8 实际仅支持 3 字节字符,utf8mb4 才是完整 utf-8,需同步设置 character_set_client/connection/results、建表 default charset=utf8mb4、连接参数及应用代码 charset。

INSERT 时出现 \xE6\x88\x91 这类错误,基本是 utf8mb4 没配全
这种十六进制错误提示(如 Incorrect string value: '\xE6\x88\x91' for column)说明 MySQL 拒绝插入该字节序列——它不是当前字段能接受的编码格式。根本原因不是“数据库没设 UTF-8”,而是客户端、连接层、表字段三者中至少有一处没对齐到 utf8mb4。
MySQL 的 utf8 是个历史包袱:最多存 3 字节字符,不支持 emoji 和部分生僻汉字;utf8mb4 才是真正的 UTF-8。5.7.8+ 版本默认推荐用 utf8mb4,但安装后不会自动覆盖旧配置。
-
character_set_client、character_set_connection、character_set_results必须全是utf8mb4,缺一不可 - 只改
character_set_server或collation-server不起作用——连接初始化时会覆盖它 - 建表语句里没写
DEFAULT CHARSET=utf8mb4,哪怕库默认是utf8mb4,新表仍可能继承latin1
命令行导入 SQL 文件前必须加 --default-character-set=utf8mb4
很多人以为改了 my.cnf 就万事大吉,结果 mysql -u root -p db_name 还是乱码。这是因为 <a style="color:#f60; text-decoration:underline;" title="mysql" href="https://m.php.cn/zt/15713.html" target="_blank">mysql</a> 客户端默认按 <code>latin1 建立连接,根本不读服务器配置。
正确做法是显式声明连接编码:
mysql --default-character-set=utf8mb4 -u root -p db_name <p>注意:<code>--default-character-set</code> 是客户端参数,必须放在 <code>-u</code> 前面;如果用 <code>source</code> 方式导入,也要先在连接后执行:</p> <pre class="brush:php;toolbar:false;">SET NAMES utf8mb4;
- 别信编辑器显示“UTF-8”就等于文件真是 UTF-8:VS Code 默认可能存成 UTF-8 with BOM,MySQL 会把 BOM 当非法字符报错
- Linux/macOS 下用
file -i dump.sql看真实编码;Windows 下用 VS Code 右下角点编码 → “Save with Encoding” → 选UTF-8(不是UTF-8 with BOM) - 如果文件真是 GBK 编码,用
iconv -f gbk -t utf8mb4 dump.sql > dump_utf8.sql转换
ALTER TABLE CONVERT TO CHARACTER SET utf8mb4 会重建表
已有表乱码,不能只改表定义,得连数据一起转。用 ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 是最直接的方式,但它会锁表、重建、复制数据——对大表很危险。
执行前务必确认:
- 表引擎是 InnoDB(MyISAM 不支持
CONVERT TO的完整语义) - 磁盘空间足够容纳两倍临时表大小
- 避开业务高峰,或提前在从库上操作验证
- 执行后检查字段实际字符集:
SHOW CREATE TABLE t中每个VARCHAR字段是否带CHARACTER SET utf8mb4
如果只想改字符集不改排序规则,用 MODIFY COLUMN 更轻量,但需逐字段写,例如:
ALTER TABLE t MODIFY name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
应用代码里漏掉 charset 参数,等于白配数据库
PHP PDO、Python PyMySQL、Java JDBC 都一样:即使数据库、表、字段全设成 utf8mb4,只要连接没声明编码,就会退化成 latin1,插入成功但查出来是问号。
各语言关键写法:
- PHP PDO:
mysql:host=localhost;charset=utf8mb4必须写进 DSN,set_charset()是补救手段,不是替代 - Python PyMySQL:
pymysql.connect(..., charset='utf8mb4'),漏掉就无效 - Java JDBC URL:
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8mb4(注意是&,不是&) - Spring Boot:
spring.datasource.url中的&要写成&,否则 properties 解析会截断
最容易被忽略的是:这些参数只影响本次连接,重启应用或连接池回收后,必须重新生效——不是配一次就永久有效。











