load data导入中文乱码的根本原因是连接层字符集(character_set_client等)非utf8mb4,而非表字符集;必须显式指定character set utf8mb4且确保客户端连接参数正确。

直接看 character_set_client、character_set_connection、character_set_results 这三项是否全为 utf8mb4;如果不是,LOAD DATA 导入中文几乎必乱码,哪怕表和文件都是 UTF-8。
为什么 LOAD DATA LOCAL INFILE 会无视表字符集?
MySQL 的 LOAD DATA 不读取目标表的 CHARACTER SET 定义,它只依赖当前连接的字符集设置来解析文件字节。也就是说,即使你的表字段是 VARCHAR(100) CHARACTER SET utf8mb4,只要连接层把文件内容当 latin1 解,中文就会被错误拆解成“锟斤拷”。
常见错误现象:
- CSV 文件用 VS Code 确认是 UTF-8 编码,导入后变成
æäºº或锟斤拷 -
SHOW CREATE TABLE显示字段是utf8mb4,但SELECT HEX(content)返回的是C3A6C2B7C2A0(这是 UTF-8 字节被当 latin1 解的结果) - 用
mysql -u root -p --default-character-set=utf8mb4命令行登录后执行LOAD DATA正常,但用 Navicat 或 Python 脚本就乱码——说明客户端连接参数没传对
LOAD DATA 必须显式声明 CHARACTER SET
不能依赖 SET NAMES utf8mb4 或配置文件,LOAD DATA 语句本身必须带 CHARACTER SET utf8mb4 子句,否则 MySQL 默认按 character_set_client 解析文件,而这个值往往不是你想要的。
实操建议:
- 导入前先确认连接字符集:
SELECT @@character_set_client, @@character_set_connection, @@character_set_results; - 在
LOAD DATA语句开头加SET NAMES utf8mb4;(仅对当前会话有效),再执行导入 -
LOAD DATA语句末尾必须写明:CHARACTER SET utf8mb4,例如:LOAD DATA LOCAL INFILE '/tmp/data.csv' INTO TABLE user FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS (name, email) CHARACTER SET utf8mb4;
- 如果 CSV 含 BOM(如 Windows 记事本保存的 UTF-8 with BOM),MySQL 会把
EF BB BF当作字段开头,导致首列错位;建议用sed -i '1s/^\xEF\xBB\xBF//' data.csv去 BOM
排查时最容易忽略的三个点
很多排查停在“表是 utf8mb4 就没问题”,其实真正断掉的环节常藏在这三处:
-
character_set_client是连接建立时由客户端声明的,比如 JDBC URL 没加characterEncoding=UTF-8,或 Pythonpymysql.connect()没设charset='utf8mb4',那这个值就是服务器默认的latin1 -
init_connect配置在my.cnf里写了,但只对普通用户生效;root 用户默认跳过init_connect,所以用mysql -u root登录时SET NAMES不会自动执行 -
LOAD DATA LOCAL INFILE受local_infile系统变量控制,如果服务端禁用了(SET GLOBAL local_infile = OFF),客户端即使开了,也会静默失败或报错ERROR 1148,此时部分驱动不会抛异常,而是把文件路径当纯文本插入,造成“数据全变成路径字符串”的假乱码
真正卡住人的,往往不是“该不该用 utf8mb4”,而是哪一层悄悄用了 latin1 却没暴露出来;每次导入前花 30 秒查一遍三件套,比事后修乱码数据省力十倍。











