如何配置MySQL服务器的时钟同步?

作者:袖梨 2026-09-01

MySQL本身不管理时钟同步,只信任系统时间;需确保NTP服务启用且偏移≤±50ms、my.cnf中配置default-time-zone='+08:00'并重启mysqld、TIMESTAMP字段会自动时区转换而DATETIME不会、客户端连接必须显式指定serverTimezone参数。

MySQL 本身不管理时钟同步,它只信任系统时间。所谓“配置 MySQL 时钟同步”,本质是确保系统时间准、MySQL 读得对、字段类型不埋雷——三者缺一不可。

systemd-timesyncd 或 chronyd 必须启用且稳定

MySQL 的 NOW()CURRENT_TIMESTAMP 全部来自系统时钟。如果系统时间漂移,MySQL 就跟着漂移,这不是 bug,是设计使然。

  1. 运行 timedatectl status,确认输出中包含 System clock synchronized: yesservice: chronyd(或 systemd-timesyncd
  2. 检查偏移量:chronyc tracking | grep "Offset"timedatectl timesync-status | grep "offset",理想值在 ±50ms 内
  3. 若未启用,执行:sudo systemctl enable --now chronyd(CentOS/RHEL)或 sudo systemctl enable --now systemd-timesyncd(Debian/Ubuntu)
  4. 容器环境需额外注意:基础镜像常默认关闭 NTP,必须在启动时挂载 host 的 /etc/chrony.conf 或注入 chronyd 进程

my.cnf 中必须写 default-time-zone,不是 time_zone

time_zone 是 SQL 层变量名,不能写进配置文件;写进去会导致 MySQL 启动失败或静默忽略。唯一合法的全局配置项是 default-time-zone

  1. 推荐写法:default-time-zone = '+08:00' —— 固定偏移,不依赖系统时区表,无兼容性风险
  2. 避免写 default-time-zone = 'Asia/Shanghai':除非你已手动执行过 mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql 并验证 SELECT COUNT(*) FROM mysql.time_zone_name; > 0
  3. 配置位置必须在 [mysqld] 段下,保存后必须 systemctl restart mysqld;热重载(如 mysqladmin reload)完全不生效
  4. 验证是否生效:SELECT @@global.time_zone, @@session.time_zone; 应返回 +08:00,而非 SYSTEM

TIMESTAMP 字段会偷偷转 UTC,DATETIME 不会

这是最容易被忽略的底层行为差异,直接导致“存进去就变时间”。

  1. TIMESTAMP 存的是 UTC 时间:插入 '2024-01-01 12:00:00' 到 +08:00 时区的 TIMESTAMP 字段,实际存入的是 2024-01-01 04:00:00(UTC)
  2. DATETIME 原样存储、原样返回,完全不转换;适合记录“固定时刻”(如发布会开始时间)
  3. 主从复制中若用 TIMESTAMP + STATEMENT 格式 binlog,主库 NOW() 写入的时间字面量,会被从库按自身 time_zone 解析,结果错位
  4. 新表设计优先用 DATETIME;已有 TIMESTAMP 字段,务必保证应用层、连接池、MySQL 全局/会话时区三者严格一致

JDBC 等客户端连接必须显式指定 serverTimezone

即使服务端配对了,客户端驱动仍可能因未明确时区而 fallback 到 SYSTEM,触发 Server returns invalid timezone 错误。

  1. JDBC URL 必须带参数:?serverTimezone=Asia/Shanghai(推荐)或 ?serverTimezone=GMT%2B8
  2. 仅加 useTimezone=true 不够,它只是开启转换逻辑,没指定具体时区照样报错
  3. 若用 serverTimezone=Asia/Shanghai,需确保 MySQL 已加载时区表(否则驱动无法解析,仍失败)
  4. Python pymysql、Node.js mysql2 等也需在连接选项中设置对应时区参数,不能依赖服务端默认
真正难的不是改哪一行配置,而是四层对齐:NTP 服务稳不稳、系统时区设没设对、MySQL 配了 default-time-zone 且重启了没、客户端连接串里有没有 serverTimezone——漏掉任意一层,NOW() 就可能“慢 8 小时”。

相关文章

精彩推荐