Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL初始化SQL中文乱码

MySQL初始化SQL中文乱码问题的解决方案

作者:m0_64642997

MySQL 容器会自动执行 init 目录中的 SQL 初始化脚本,SQL 文件中的中文内容正常,但数据导入数据库后变成了乱码,这种现象是典型的 UTF-8 字节被按 latin1 解析后,再写入 UTF-8 字段所产生的乱码,所以本文给大家介绍了详细解决方案,需要的朋友可以参考下

1. 问题现象

项目通过 Docker Compose 启动 MySQL:

docker compose up -d

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

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

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

2. 检查结果

实际检查后确认:

修改前的连接字符集为:

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

以上就是MySQL初始化SQL中文乱码问题的解决方案的详细内容,更多关于MySQL初始化SQL中文乱码的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文