欢迎光临
我们一直在努力

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

1. 问题现象

项目通过 Docker Compose 启动 MySQL:

docker compose up -d

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

柳岩 -> 柳岩
苹果 -> 苹果

这种现象是典型的 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 的字体或显示设置问题。

修改前的连接字符集为:

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 服务中增加:

services:
mysql:
image: mysql:8.0.30
command: –skip-character-set-client-handshake

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

修改后重建容器:

docker compose up -d –force-recreate mysql

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

5. 验证结果

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

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

修改后的实际结果为:

character_set_client utf8mb4
character_set_connection utf8mb4
character_set_results utf8mb4

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

6. 已有乱码数据的处理

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

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

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

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 导入中文时再次出现乱码。

赞(0)
未经允许不得转载:171主机测评 » MySQL 初始化 SQL 中文乱码问题总结
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址