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

相关推荐
实战派K8S&DB1 小时前
TDSQL 核心模块与进程体系
运维·数据库·分布式·sql·mysql
FfHUCisI1 小时前
Go 性能分析工具 pprof:CPU、Heap 与 Goroutine 实战
数据库·golang
仍然.1 小时前
Redis---分布式锁
数据库·redis·分布式
ly76891 小时前
MongoDB 副本集选举风暴排查:从心跳超时到 Journal 刷盘阻塞
数据库·mongodb·php·mongodb 副本集·选举风暴·journal 刷盘·writeconcern
Lost_the_wind1 小时前
MySQL 学习笔记三
笔记·学习·mysql
刘天远1 小时前
Agent成本核算实现:事件表、状态分布与Python归集
前端·数据库·人工智能·python
hey you~2 小时前
通话记录与工单关联数据库设计:ER图、中间表、索引优化与分库分表(2026版)
数据库·分库分表·客服系统·数据一致性·后端开发·通话记录·跨系统查询
java_logo2 小时前
Docker 部署 OpenViking:轻松搭建 AI Agent 上下文数据库平台
数据库·人工智能·docker·agent·火山引擎·openviking·轩辕镜像
Codiggerworld2 小时前
Redis 正式接入 AI:当“最懂速度的数据库“开始解决“记忆问题“
数据库·人工智能·redis