MySQL在虚拟机中时间不准的根本原因是虚拟机系统时间漂移,而MySQL仅被动信任并缓存启动时的系统时间;需同步宿主机NTP、正确挂载时区文件、重启mysqld三者缺一不可。

MySQL 在虚拟机里时间不准,根本不是 MySQL 的问题,而是它照搬了虚拟机里错误的系统时间——而虚拟机时间本身,常因宿主机同步策略、时区挂载缺失或 NTP 服务未启用而漂移。
虚拟机系统时间为什么容易漂移
虚拟机不自带高精度时钟,它的“当前时间”完全依赖宿主机提供或自身 NTP 同步。常见失效场景包括:
- VMware/VirtualBox/KVM 未开启“同步客户机时间与主机时间”选项(尤其 Windows 客户机默认关闭)
- Linux 虚拟机里
chronyd或systemd-timesyncd服务未启用,timedatectl status显示System clock synchronized: no - 云厂商镜像(如 CentOS minimal)默认不装
tzdata包,导致/usr/share/zoneinfo/Asia/Shanghai路径不存在,进而影响 MySQL 加载命名时区 - 容器化部署时,Docker 默认不挂载宿主机时区文件,
/etc/localtime是空或软链指向不存在路径
MySQL 启动后才读一次系统时间,改了也白改
MySQL 启动时只读取一次系统时区和当前时间戳,之后全程缓存。这意味着:
- 即使你用
date -s手动改了虚拟机时间,NOW()仍返回旧值,直到重启mysqld -
timedatectl set-timezone Asia/Shanghai生效后,必须重启mysqld,否则@@global.time_zone还是SYSTEM且指向旧时区 - 在 Kubernetes 中用 ConfigMap 挂载
my.cnf修改default-time-zone,若 Pod 未重建,配置根本不加载
Docker 容器里 MySQL 时间不准的典型表现
容器环境比裸机更易踩坑,因为时区是“双层嵌套”问题:
- 执行
docker exec -it mysql-container date返回的时间 ≠ 宿主机date,说明容器系统时间已偏移 - 此时即使
my.cnf写了default-time-zone = '+08:00',MySQL 仍可能 fallback 到SYSTEM——因为容器内没有/usr/share/zoneinfo,MySQL 认不出Asia/Shanghai,又发现SYSTEM对应的时区文件缺失,最终按 UTC 解析 - 验证方式:进容器跑
ls -l /etc/localtime,如果指向/usr/share/zoneinfo/UTC或是断链,就是根源
真正要检查的三个地方,缺一不可
别只盯着 my.cnf,以下三处必须同时对齐:
- 宿主机 NTP 状态:
timedatectl timesync-status | grep offset,偏移量稳定在 ±50ms 内才算可靠 - 虚拟机/容器系统时区:
timedatectl | grep "Time zone",不是看date输出,而是看这一行是否为你期望的值(如Asia/Shanghai) - MySQL 实际生效时区:
SELECT @@global.time_zone, @@session.time_zone;,两个都得是+08:00或明确的命名时区,不能一个是SYSTEM一个是+08:00
最常被忽略的是:改完宿主机时区或 NTP 配置后,忘了重启虚拟机或容器——系统时间变了,但 MySQL 进程还活在旧时间快照里。


















