根本原因是mysql客户端连接时未显式指定字符集,导致默认按latin1协商,即使SQL文件为UTF-8无BOM,插入中文仍变问号;必须加--default-character-set=utf8mb4参数强制连接层使用utf8mb4。

mysql命令行导入SQL文件时中文变问号
根本原因不是SQL文件本身有问题,而是mysql客户端连接时没协商到UTF-8。即使data.sql是UTF-8无BOM,mysql -u root -p db 这条命令默认仍按<code>latin1解析输入流。
- 先用
file -i data.sql确认真实编码,有BOM就用sed -i '1s/^\xef\xbb\xbf//' data.sql清除 - 显式指定字符集:改用
mysql --default-character-set=utf8mb4 -u root -p db - 或在命令前加环境变量:
MYSQL_CHARSET=utf8mb4 mysql -u root -p db - 避免依赖
~/.my.cnf里[client]段配置——CI/CD环境常不生效
show variables like 'char%'显示全是latin1
说明MySQL服务端默认字符集没改,仅改表或数据库层级无法根治。5.7+版本编译默认仍是latin1,必须从配置文件切入。
- 编辑
/etc/my.cnf(Linux)或my.ini(Windows),在[mysqld]下加:character_set_server = utf8mb4 - 在同一文件的
[client]段加:default-character-set = utf8mb4 - 重启MySQL服务后,
show variables like 'character_set%'中character_set_server和character_set_database才可能变成utf8mb4 - 注意:
utf8在MySQL里是utf8mb3,存emoji会失败,必须用utf8mb4
已存在的库/表怎么批量转utf8mb4
ALTER语句只能改结构,不能自动转换存量数据的字节序列。如果原数据已用错误编码存入(比如latin1里塞了UTF-8字节),直接改字符集会导致更乱。
- 先确认当前数据是否“假乱码”:用
SELECT HEX(col_name) FROM table LIMIT 1看十六进制值。若显示E4B8AD(“中”的UTF-8编码),说明数据本身正确,只是显示层错 - 安全转换顺序:
ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;→ALTER TABLE tb_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 字段级单独处理:
ALTER TABLE tb_name CHANGE col_name col_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 别漏掉
information_schema外的系统库,如mysql库里的user表也需同步改
PHP/Python连接MySQL仍乱码
应用层连接参数没覆盖会话层字符集,导致SET NAMES utf8mb4没执行或执行晚于查询。
- PHP PDO:DSN里必须带
;charset=utf8mb4,例如mysql:host=localhost;dbname=test;charset=utf8mb4 - Python PyMySQL:创建连接时传
charset='utf8mb4'参数,不能只靠init_command="SET NAMES utf8mb4" - Java JDBC:URL加
?characterEncoding=utf8mb4&useUnicode=true,且驱动版本需≥5.1.13 - 验证方法:连接后立即查
SELECT @@character_set_client, @@character_set_connection, @@character_set_results,三者都应为utf8mb4
CONVERT TO会把“锟斤拷”当成合法latin1字符再转成utf8mb4,结果还是乱码。必须人工识别原始编码再重建数据。


















