MySQL中文乱码是开发中非常常见的问题,本质原因是数据存储、传输、读取过程中使用的字符集不一致,导致中文编码无法正确解析。要解决这类问题,需要先从字符集的基本逻辑入手,再逐步排查每个环节的配置。

一、MySQL字符集基础
MySQL支持多种字符集,其中utf8mb4是当前最推荐的中文存储字符集,它完全兼容utf8,还能支持emoji等特殊字符。常见的字符集相关配置项有四个层级:
- 服务端字符集:MySQL服务实例全局默认的字符集
- 数据库字符集:单个数据库默认的字符集
- 表字符集:单张表默认的字符集
- 字段字符集:表中单个字段的字符集,优先级高于表字符集
另外还有连接字符集,用于指定客户端和服务器之间传输数据使用的编码,需要和存储字符集匹配才能避免乱码。
二、常见乱码场景排查
遇到中文乱码时,先按以下步骤排查当前环境的字符集配置:
1. 查看MySQL全局字符集配置
执行如下SQL命令查看当前服务端的字符集设置:
-- 查看全局字符集相关变量 SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';
正常情况下,character_set_server、character_set_database、character_set_client、character_set_connection、character_set_results都应该设置为utf8mb4,排序规则使用utf8mb4_general_ci或者utf8mb4_unicode_ci。
2. 查看已有库表的字符集
如果需要检查已有数据库的字符集,可以用以下命令:
-- 查看指定数据库的字符集 SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = '你的数据库名'; -- 查看指定表的字符集 SHOW TABLE STATUS FROM 你的数据库名 LIKE '你的表名';
三、完整解决方案
1. 修改MySQL服务端配置
找到MySQL的配置文件my.cnf(Linux系统)或者my.ini(Windows系统),在对应区域添加如下配置:
[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'
修改完成后重启MySQL服务,配置即可生效。
2. 新建库表时指定字符集
新建数据库和表时,显式指定字符集可以避免继承到旧的错误配置:
-- 新建数据库时指定字符集
CREATE DATABASE IF NOT EXISTS test_db
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATION utf8mb4_general_ci;
-- 新建表时指定字符集
USE test_db;
CREATE TABLE IF NOT EXISTS user_info (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
remark VARCHAR(200)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;3. 客户端连接时指定字符集
如果是程序连接MySQL,需要在连接参数中指定字符集,避免连接传输时编码错误。以下是不同语言的示例:
PHP连接示例
<?php
$conn = new mysqli('127.0.0.1', 'root', 'password', 'test_db');
// 设置连接字符集
$conn->set_charset('utf8mb4');
?>Java连接示例
import java.sql.Connection;
import java.sql.DriverManager;
public class MysqlTest {
public static void main(String[] args) throws Exception {
String url = "jdbc:mysql://127.0.0.1:3306/test_db?useUnicode=true&characterEncoding=utf8mb4";
String user = "root";
String password = "password";
Connection conn = DriverManager.getConnection(url, user, password);
}
}4. 修复已有乱码数据
如果已有的表已经出现乱码,需要先导出数据,修改字符集后重新导入:
# 导出数据,指定字符集为utf8mb4 mysqldump -u root -p --default-character-set=utf8mb4 test_db > test_db.sql # 修改导出的sql文件,确保建表语句中字符集为utf8mb4 # 删除旧库,重新创建新库后导入 mysql -u root -p --default-character-set=utf8mb4 test_db < test_db.sql
四、验证方案是否生效
配置完成后,可以插入中文数据验证是否正常:
USE test_db;
INSERT INTO user_info (username, remark) VALUES ('张三', '测试中文存储');
SELECT * FROM user_info;如果查询结果中中文正常显示,说明乱码问题已经彻底解决。