MySQL写入中文报错主因是客户端、连接层、表结构三者字符集不一致,典型错误为1366或Incorrect string value;需确认表字段为utf8mb4、连接层显式指定charset=utf8mb4、客户端数据源编码正确,并统一my.cnf中client[mysqld]三处配置。

MySQL写入中文报错,绝大多数情况不是编码问题本身,而是客户端、连接层、表结构三者字符集不一致导致的隐性冲突。直接改utf8mb4不一定能解决,得看哪一层卡住了。
INSERT时提示1366或Incorrect string value
这是最典型的中文写入失败现象,错误信息里通常带Incorrect string value或1366,说明MySQL在尝试把字节流存进字段时发现它不符合当前列的字符集定义。
- 先确认表字段用的是
utf8mb4,不是utf8(MySQL里的utf8实际只支持3字节UTF-8,不支持emoji和部分生僻中文) - 执行
SHOW CREATE TABLE your_table;,检查CHARACTER SET和COLLATE是否为utf8mb4和utf8mb4_unicode_ci(或utf8mb4_general_ci) - 如果字段是
utf8mb4但依然报错,大概率是连接层没设对——客户端发来的数据被MySQL按默认字符集(如latin1)解码了
连接初始化没指定charset=utf8mb4
很多驱动默认不主动协商字符集,尤其Python的pymysql、PHP的mysqli、Node.js的mysql2,必须显式声明。
- PyMySQL示例:
conn = pymysql.connect(..., charset='utf8mb4', collation='utf8mb4_unicode_ci') - PHP mysqli:
$mysqli->set_charset("utf8mb4")要在connect()之后立即调用 - 命令行mysql客户端:启动时加
--default-character-set=utf8mb4,或在配置文件[client]段写default-character-set = utf8mb4 - Spring Boot JDBC URL里要加
?characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai
客户端实际发送的是Latin1编码的字节
常见于从Excel、网页表单、旧系统接口拿到的数据,表面看着是中文,但原始字节是GBK或GB2312编码,而MySQL按utf8mb4去解,自然乱码+报错。
- 用
SELECT HEX('你的中文');查一下MySQL收到的十六进制值,如果是类似E4B8AD(UTF-8),说明编码正确;如果是D6D0(GBK),说明源头没转码 - 不要在SQL里硬拼字符串:
INSERT INTO t VALUES ('中文')——如果客户端编码不对,这句就已错 - 一律用参数化查询:
cursor.execute("INSERT INTO t (name) VALUES (%s)", ("张三",)),让驱动负责编码转换
my.cnf里只改了[mysqld]没动[client]和[mysql]
很多人只改[mysqld]下的character-set-server = utf8mb4,但客户端连接时仍按latin1握手,导致写入失败。
- 必须同时配全三处:
[client]、[mysql]、[mysqld]都加上default-character-set = utf8mb4(或character-set-client-handshake = FALSE强制服务端主导) - 改完重启MySQL:
sudo systemctl restart mysql,然后连上去执行SHOW VARIABLES LIKE 'character_set%';确认所有character_set_client、character_set_connection、character_set_results都是utf8mb4 - 注意:有些云数据库(如阿里云RDS)不允许改
my.cnf,得通过控制台参数模板设置
真正麻烦的不是改配置,而是排查时容易盯住表结构或SQL语句,却忽略连接建立那一刻的字符集协商——那个握手包里传的charset才是第一道关卡。


















