必须修改my.cnf/my.ini的mysqld[mysql]三段并重启验证,再alter已有库表,客户端连接仍需显式指定charset;仅改character-set-server无效。

MySQL安装后默认字符集大概率不是utf8mb4,直接存中文或emoji会报Incorrect string value错误——必须改配置文件、重启、再手动升级已有库表,缺一环都白忙。
my.cnf/my.ini必须改三处段落,只改[mysqld]没用
MySQL字符集生效靠客户端、连接、服务端三层协同,仅在[mysqld]里写character-set-server = utf8mb4,命令行连上去character_set_client可能还是latin1。
-
[mysqld]段加两行:character-set-server = utf8mb4+collation-server = utf8mb4_0900_ai_ci(MySQL 8.0+ 推荐,别用utf8mb4_unicode_ci除非兼容老应用) -
[client]段加:default-character-set = utf8mb4(影响mysql、mysqldump等所有客户端工具) -
[mysql]段加:default-character-set = utf8mb4(专治mysql -u root -p连上后仍是utf8的问题) - Windows用户注意路径:
C:\ProgramData\MySQL\MySQL Server X.X\my.ini(不是Program Files目录);宝塔用户去【软件商店】→ MySQL → 【设置】→ 【配置修改】直接编辑
重启后必须验证四个变量全为utf8mb4
只改配置不验证,等于没改。连上MySQL后执行:SHOW VARIABLES LIKE 'character%';,重点盯这四行:
character_set_clientcharacter_set_connectioncharacter_set_resultscharacter_set_server
任一值是utf8(即utf8mb3)或latin1,说明配置没加载成功——常见原因是段落写错位置(比如塞进[mysqld_safe])、文件路径不对、或被其他同名配置覆盖。Linux下用mysql -h 127.0.0.1 -u root -p强制走TCP,能绕过socket连接不读[client]段的坑。
已有数据库和表必须手动ALTER,不会自动升级
character-set-server只管新建库表,对老对象完全无效。哪怕你验证全绿,老表里VARCHAR字段存emoji仍会报错。
- 先改库:
ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; - 再改表:
ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;(必须用CONVERT TO,只MODIFY COLUMN不会重编码已有数据) - 特别注意
TEXT/VARCHAR字段长度:utf8mb4单字符最多占4字节,原VARCHAR(255)在InnoDB里实际占1020字节,可能触发Row size too large错误,必要时缩字段长度
应用连接层必须显式指定charset=utf8mb4
服务端和表都改了,PHP/Java/Python连上去还是乱码?八成是应用代码里漏了字符集声明。MySQL握手时客户端驱动会主动报自己用的编码,这个声明优先级高于服务端配置。
- PHP PDO:
mysql:host=localhost;dbname=test;charset=utf8mb4(DSN里charset参数不能少) - Java JDBC:
jdbc:mysql://host/db?useUnicode=true&characterEncoding=utf8mb4(注意是utf8mb4,不是utf8) - Python PyMySQL:
pymysql.connect(..., charset='utf8mb4') - 命令行临时方案:
mysql -u root -p --default-character-set=utf8mb4 db_name
最易被忽略的是:即使配置文件写了default-character-set = utf8mb4,如果应用代码里没传charset参数,连接进来时三件套(client/connection/results)仍可能是latin1——验证时得看SHOW VARIABLES输出,而不是想当然认为“配了就完事”。











