mysql字符集及编码

一、字符集与编码基础

常见字符集

字符集 说明 适用场景
latin1 西欧单字节编码(默认旧版本MySQL) 早期英文环境
utf8 MySQL的“伪UTF-8”,最多3字节,不支持emoji 常见于旧系统
utf8mb4 真·UTF-8,最多4字节,支持emoji ✅ 现代系统推荐
gbk/gb2312 中文编码,2字节 仅限遗留系统

二、MySQL 字符集的层级(四层)

每个层级都可能引起编码不一致导致乱码:

层级 作用范围 查看命令 修复策略
1. 服务器级 默认全局字符集 SHOW VARIABLES LIKE 'character_set_%'; 修改配置文件或运行时设置
2. 数据库级 当前数据库默认字符集 SHOW CREATE DATABASE db_name; ALTER DATABASE db_name CHARACTER SET utf8mb4;
3. 表级 表的默认字符集 SHOW CREATE TABLE table_name; ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4;
4. 列级 单列的字符集 SHOW FULL COLUMNS FROM table_name; ALTER TABLE table_name MODIFY col_name VARCHAR(255) CHARACTER SET utf8mb4;

三、乱码的常见场景与原因

场景 问题来源 示例
客户端插入中文变成“???” 客户端连接编码与服务器不一致 连接未设置 SET NAMES utf8mb4
查询出来乱码 连接层编码不同 JDBC、Python等未声明 charset=utf8mb4
导入SQL文件乱码 文件编码与数据库不符 SQL文件是GBK,数据库是UTF8
网站显示乱码 PHP/HTML未指定正确charset <meta charset="utf-8"> 缺失或与DB不符

四、修复乱码的通用步骤

1. 确认数据“原始状态”

1
2
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

确认数据库、表、列、连接层的编码分别是什么。


2. 确认当前连接编码

1
2
3
SHOW VARIABLES LIKE 'character_set_client';
SHOW VARIABLES LIKE 'character_set_connection';
SHOW VARIABLES LIKE 'character_set_results';

如不一致可强制指定:

1
2
3
SET NAMES utf8mb4;
-- 或在客户端配置:
mysql -uroot -p --default-character-set=utf8mb4

3. 检查表和列编码

1
SHOW CREATE TABLE table_name;

如果发现表或列是 latin1utf8 等旧字符集,可统一转换:

1
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

注意:CONVERT TO CHARACTER SET重新编码已有数据,而不是仅修改元数据。


4. 修复已经“存错”的数据(乱码)

情况1:存进去就是乱码(编码错误写入)
可以导出→转码→重新导入:

1
2
3
4
5
mysqldump --default-character-set=latin1 db > dump_latin1.sql

iconv -f latin1 -t utf8 dump_latin1.sql > dump_utf8.sql

mysql --default-character-set=utf8mb4 db < dump_utf8.sql

情况2:查询时乱码(连接层问题)
无需修复数据,只需修正连接参数:

1
mysql -uuser -p --default-character-set=utf8mb4

或 JDBC:

1
jdbc:mysql://host/db?useUnicode=true&characterEncoding=utf8mb4

五、永久修复建议

编辑 /etc/my.cnf

1
2
3
4
5
6
7
8
9
10
[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
init_connect='SET NAMES utf8mb4'

重启服务:

1
systemctl restart mysqld

六、修复流程总览

flowchart TD
A[发现乱码问题] --> B[确认客户端字符集]
B --> C[确认MySQL服务端字符集]
C --> D[确认数据库/表/列字符集]
D --> E{数据是否本身被错误编码?}
E -->|否| F[统一配置字符集 utf8mb4]
E -->|是| G[导出→iconv转码→重新导入]
F --> H[测试查询结果]
G --> H
H --> I[更新客户端连接参数]
I --> J[问题解决 ✅]

七、最终建议

目标 建议
新项目 全面采用 utf8mb4
旧系统 分阶段迁移字符集
Web开发 页面、API、数据库统一UTF-8
数据导出导入 总是指定 --default-character-set