MySQL 初始化 SQL 中文乱码问题总结

1. 问题现象

项目通过 Docker Compose 启动 MySQL:

powershell 复制代码
docker compose up -d

MySQL 容器会自动执行 init 目录中的 SQL 初始化脚本。SQL 文件中的中文内容正常,但数据导入数据库后变成了乱码,例如:

text 复制代码
柳岩 -> 柳岩
苹果 -> 苹果

这种现象是典型的 UTF-8 字节被按 latin1 解析后,再写入 UTF-8 字段所产生的乱码。

2. 检查结果

实际检查后确认:

  • init/01-user.sql 和 init/02-order.sql 的文件内容为 UTF-8,SQL 文件本身没有乱码。
  • MySQL 服务端默认字符集为 utf8mb4。
  • spring-cloud-user 和 spring-cloud-order 数据库字符集正常。
  • 容器中 mysql 命令行客户端的默认连接字符集为 latin1。
  • 查询数据的十六进制内容后,确认乱码已经被实际写入数据库,不是 DataGrip 的字体或显示设置问题。

修改前的连接字符集为:

text 复制代码
character_set_client     latin1
character_set_connection latin1
character_set_results    latin1

3. 根本原因

MySQL 官方镜像在首次创建数据目录时,会使用容器内的 mysql 客户端执行 /docker-entrypoint-initdb.d 下的 SQL 脚本。

虽然 SQL 文件和 MySQL 服务端都使用 UTF-8,但客户端在建立连接时声明的字符集是 latin1。MySQL 因此会把 SQL 文件中的 UTF-8 中文字节当成 latin1 字符解析,然后转换为 UTF-8 存入数据库,最终造成乱码。

4. 解决方案

在 docker-compose.yml 的 MySQL 服务中增加:

yaml 复制代码
services:
  mysql:
    image: mysql:8.0.30
    command: --skip-character-set-client-handshake

该参数会让 MySQL 服务端忽略客户端提交的字符集,使用服务端的默认字符集 utf8mb4。

修改后重建容器:

powershell 复制代码
docker compose up -d --force-recreate mysql

此操作只重建 MySQL 容器,不会删除已有数据卷。

5. 验证结果

可以使用以下命令检查连接字符集:

powershell 复制代码
docker compose exec -T mysql mysql -uroot -p123 -e "SHOW VARIABLES WHERE Variable_name IN ('character_set_client','character_set_connection','character_set_results')"

修改后的实际结果为:

text 复制代码
character_set_client     utf8mb4
character_set_connection utf8mb4
character_set_results    utf8mb4

说明字符集设置已经生效。

6. 已有乱码数据的处理

修改连接字符集只能防止之后导入的数据继续乱码,不会自动修复已经存入数据库的乱码数据。

Docker 中的 MySQL 初始化脚本只会在 /var/lib/mysql 数据目录为空时执行一次。因此,仅再次执行 docker compose up -d 不会重新导入初始化 SQL。

如果现有数据可以删除,可执行:

powershell 复制代码
docker compose down -v
docker compose up -d

警告:docker compose down -v 会删除 Compose 项目创建的数据卷,包括当前 MySQL 中的所有数据。执行前应确认数据可以丢弃,或已经完成备份。

删除数据卷并重新启动后,MySQL 会重新执行 init 目录中的 SQL,此时中文数据会按 utf8mb4 正确导入。

7. 结论

本次乱码的根本原因不是 SQL 文件编码、数据库字段字符集或 DataGrip 显示设置,而是 MySQL 初始化脚本执行时,客户端和服务端之间使用了错误的 latin1 连接字符集。

通过在 Docker Compose 中增加 --skip-character-set-client-handshake,已将连接字符集统一为 utf8mb4,可以避免后续初始化 SQL 导入中文时再次出现乱码。

相关推荐
ClickHouseDB5 小时前
ClickHouse Cloud 与 Snowflake 实时性价比对比:CostBench 测试中的 412 倍差距来
运维·数据库·系统架构
m0_639906945 小时前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
时间售卖铺6 小时前
触发器与函数实战:MySQL高效编程秘诀
运维·数据库·mysql·云原生
qetfw6 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
数智园区合作社7 小时前
问数平台怎么把同一个指标锁成一个数
大数据·数据库·人工智能·ai
lbb 小魔仙7 小时前
Windows搭建PaddleOCR+飞书Webhook自动打卡通知机器人:识别、推送与远程触发完整教程
数据库·人工智能·prometheus·时序数据库
captain3768 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
心中有你02149 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
龙亘川9 小时前
综合素质评价业务建模:从过程性评价到成长档案全链路闭环
数据库·智慧城市·数据可视化
数据库小组9 小时前
NineData 实战教程:MySQL 5.5 数据迁移同步到 MySQL 8.0(跨版本升级)
数据库·mysql·mysql优化·数据库开发·数据库迁移·版本升级·数据复制