MySQL时间不准的根本原因是系统时间不准或MySQL未正确识别时区:需先启用NTP确保系统时间同步(timedatectl status显示“System clock synchronized: yes”),再配置default-time-zone='+08:00'并重启mysqld,同时避免TIMESTAMP字段引发的时区转换陷阱。

MySQL 本身不负责时间同步,它只被动信任系统时间;所谓“配置时间同步”,本质是确保系统时间准、MySQL 读得对、字段类型不埋雷。
为什么改了 default-time-zone 还是不准
MySQL 启动时只读一次系统时区和 default-time-zone 配置,之后就缓存起来。如果系统时间在 MySQL 启动后被手动改过(比如 date -s),或 NTP 服务没跑稳,NOW() 就会“漂移”——这不是 MySQL bug,是它照搬了错误的输入。
- 必须先确认
timedatectl status显示System clock synchronized: yes,且NTP service: active - 检查偏移量:
chronyc tracking | grep "Offset"或timedatectl timesync-status | grep "offset",稳定在 ±50ms 内才算可靠 - 别跳过重启:改完
/etc/my.cnf中的default-time-zone后,必须systemctl restart mysqld,热重载不生效 - 验证是否生效:
SELECT @@global.time_zone, @@session.time_zone;应返回你设的值(如+08:00),不是SYSTEM
default-time-zone = '+08:00' 和 'Asia/Shanghai' 怎么选
用 '+08:00' 更安全,尤其在线上环境;用 'Asia/Shanghai' 要多走一步且有失败风险。
-
'+08:00'是固定偏移,不依赖 MySQL 时区表,MySQL 启动即认,无兼容性问题 -
'Asia/Shanghai'需要mysql.time_zone_name表已加载,否则启动直接报错ERROR 1298 (HY000): Unknown or incorrect time zone - 若坚持用命名时区,必须执行:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql(路径可用find /usr -name zoneinfo -type d 2>/dev/null确认) - 执行后验证:
SELECT COUNT(*) FROM mysql.time_zone_name;结果应 > 0(通常 500+ 条)
TIMESTAMP 字段为什么会“自动变时间”
这是最常被忽略的底层行为:TIMESTAMP 存的是 UTC,读出来才按当前时区转;DATETIME 原样存原样取,完全不转换。
- 插入
'2024-01-01 12:00:00'到TIMESTAMP字段,在+08:00下实际存为2024-01-01 04:00:00(UTC) - 换一个会话设
SET time_zone = '+00:00'再查,看到的就是2024-01-01 04:00:00——不是“错了”,是设计如此 - 新表设计优先用
DATETIME,除非你明确需要跨时区自动归一化(比如全球用户共用一套日志时间) - 已有
TIMESTAMP字段,务必保证应用层、连接池、MySQL 全局/会话时区三者一致,否则WHERE ts > '2024-01-01'可能因会话时区不同返回意外结果
容器环境里时间同步特别容易翻车
Docker/K8s 容器默认共享宿主机内核时钟,但时区文件和 NTP 服务往往没透传,导致 date 和 NOW() 对不上。
- 宿主机必须已启用 NTP(
chronyd或systemd-timesyncd),且时间已稳 - 容器启动时挂载宿主机时区:
-v /etc/localtime:/etc/localtime:ro,否则容器内date可能显示 UTC - MySQL 镜像若基于 Alpine,
/usr/share/zoneinfo路径可能不存在,mysql_tzinfo_to_sql会失败,此时只能用+08:00 - K8s 中建议用
initContainer检查宿主机timedatectl status,失败则拒绝启动主容器
真正难的不是配参数,而是把“系统时间→MySQL读取→字段类型→应用连接”这四层时区逻辑串成一条线。任何一层断开,NOW() 就可能在某个环节悄悄偏移几小时,而错误日志里往往只显示“数据时间异常”,不会告诉你哪一层漏了校准。











