7
0
0

Docker 部署 MySQL 9.2.0:搞定中文乱码与时区

2026-10-27
2026-10-30
文章摘要
|

背景与目标

相比 SQL Server,MySQL 在个人电脑上"装起来没那么痛苦",但也逃不过那几个经典系统级问题:服务注册冲突、端口被占、卸载不干净、还有最烦的字符集乱码和时区不对——数据库看着装好了,一写中文就变 ???,查个时间又差 8 个小时。

这些其实都是"启动参数"问题,不是数据库装错了。用 Docker 部署 MySQL,把字符集、时区、端口、认证方式全部在你可见的 docker-compose.yaml 里一次定好,可复现、可删可重来。本文给你一份验证用的配置,开箱即用。

提示:本文作者宿主是 Windows (Docker Desktop)。镜像通过华为云镜像站拉取(国内拉取更快更稳)。

步骤

第 0 步:确认 Docker Desktop 已就绪

docker version
docker compose version

输出版本号即 OK。

第 1 步:准备目录

mkdir mysql && cd mysql

第 2 步:写 docker-compose.yaml

新建 docker-compose.yaml,整段复制:

services:
  mysql:
    image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mysql:9.2.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: "YourStrong!Passw0rd"
      MYSQL_TZ: "Asia/Shanghai"
      TZ: "Asia/Shanghai"
      LANG: "C.UTF-8"
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --default-time-zone=+8:00
    ports:
      - "3306:3306"
    volumes:
      - ./mysql-data:/var/lib/mysql
    restart: unless-stopped

要点:

  • MYSQL_ROOT_PASSWORD:root 密码,务必设一个强密码。

  • 字符集 utf8mb4 + 排序规则 utf8mb4_unicode_ci:中文不乱的根源。

  • 时区双保险:环境变量 TZ + 服务参数 --default-time-zone=+8:00。

  • 数据卷 ./mysql-data 绑定挂载,数据落盘。

第 3 步:启动

docker compose up -d

首次启动 MySQL 要初始化数据目录,需要一点时间。看日志:

docker compose logs -f mysql

看到 ready for connections 即就绪。

第 4 步:连接验证

进容器用命令行连:

docker compose exec mysql mysql -uroot -p

输入密码(就是 MYSQL_ROOT_PASSWORD)。能进到 mysql> 提示符即成功。

验证字符集和时区:

SHOW VARIABLES LIKE 'character_set_server';
SELECT NOW();

character_set_server 应为 utf8mb4,NOW() 应显示北京时间。

踩坑与解决

1. 连接报 Authentication plugin 'caching_sha2_password' cannot be loaded

  • 问题:用一些老客户端 / 旧版程序连不上,报 authentication plugin 错误。

  • 复现:旧版 JDBC 驱动或老 Navicat 连接时报 caching_sha2_password ... cannot be loaded。

  • 根因:MySQL 8.0+ 默认认证插件是 caching_sha2_password,早于 8.0 的客户端不认识它。

  • 解决:a) 升级客户端到支持 MySQL 8/9 的版本(推荐);b) 确实没法升级时,为特定用户降级为 mysql_native_password:

    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourStrong!Passw0rd';
  • 验证:旧客户端能正常连接。

2. 中文变成 ??? / 乱码

  • 问题:插入中文查询出来全是问号。

  • 复现:INSERT 中文后 SELECT 显示 ???。

  • 根因:默认字符集或排序规则不是 utf8mb4。注意 utf8 在 MySQL 里其实是 utf8mb3,存不全四字节字符。

  • 解决:本教程的 yaml 已用 --character-set-server=utf8mb4 和 --collation-server=utf8mb4_unicode_ci。若已有库建错了,保证库表和连接串都用 utf8mb4,并确认连接用 SET NAMES utf8mb4(或 JDBC 连接参数 characterEncoding=utf8)。

  • 验证:插入中文后 SELECT 正常显示。

3. 时间比北京时间差 8 小时

  • 问题:NOW() 返回的是 UTC 时间,比本地慢 8 小时。

  • 复现:应用存的"当前时间"与本地时间不符。

  • 根因:容器默认时区是 UTC,未设 TZ。

  • 解决:yaml 已设环境变量 TZ=Asia/Shanghai + MYSQL_TZ + 服务参数 --default-time-zone=+8:00 三重保证。若容器已启动,改配置后 docker compose up -d 重建。

  • 验证:SELECT NOW() 返回北京时间。

4. 数据丢了?(重启后表消失)

  • 问题:删容器重建后,之前建的数据没了。

  • 复现:docker compose down && docker compose up -d 后库里是空的。

  • 根因:没挂数据卷,数据存在容器可写层,容器销毁即丢失。

  • 解决:yaml 已挂 ./mysql-data:/var/lib/mysql 绑定卷。数据持久化在你目录下的 mysql-data/。

  • 验证:建个测试表,docker compose down 再 up,表仍在。

5. 端口 3306 被占

  • 问题:docker compose up -d 报端口被占用。

  • 复现:报 port is already allocated 或 address already in use。

  • 根因:本机已有 MySQL 服务或其他程序占用 3306。

  • 解决:改外部端口,如 3307:3306;连接时用 localhost:3307。或停掉本机残留的 MySQL 服务。

  • 验证:docker compose up -d 成功,客户端连新端口正常。

实操截图

容器运行

ScreenShot_2026-10-29_091932_314.png

连接数据库

ScreenShot_2026-10-29_092004_999.png
ScreenShot_2026-10-29_092014_546.png

小结与参考

  • 用 Docker 部署 MySQL 9.2.0,把字符集、时区、认证一次性在配置里定好,可复现、可重来。

  • 字符集必用 utf8mb4(别用会截断中文符号的 utf8),时区设 Asia/Shanghai。

  • MySQL 8.0+ 默认 caching_sha2_password,老客户端连不上时优先升级客户端。

  • 数据卷挂 ./mysql-data,容器销毁不丢数据。

  • 端口被占改外部端口即可。

参考:

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

Docker 部署 MySQL 9.2.0:搞定中文乱码与时区
/archives/docker-bu-shu-mysql-9.2.0-gao-ding-zhong-wen-luan-ma-yu-shi-qu
作者
隔壁老陈
发布于
2026-10-27
许可协议
CC BY-NC-SA 4.0

评论