首页/数据/数据库速查/时区设置与时间显示排查

时区设置与时间显示排查

时间函数结果取决于会话时区:云数据库与容器常是 UTC,业务按东八区理解就会出现「时间差 8 小时」。

数据库速查数据更新于 2026-10-13

时区差异从哪来

时间函数的输出取决于会话时区:云数据库与容器镜像常默认 UTC,业务按东八区理解就会出现固定的 8 小时偏差。更隐蔽的是 TIMESTAMP 与 DATETIME 的差异:TIMESTAMP 底层存 UTC、读取时按会话时区换算,DATETIME 则原样存取不换算,两者混用最容易出问题。

基本信息

适用MySQL 5.7 / 8.0
查看SELECT @@global.time_zone, @@session.time_zone;
取值方式固定偏移如 +08:00,或命名时区如 Asia/Shanghai(需加载时区表)
持久化my.cnf 的 [mysqld] 段设置 default-time-zone

查看与设置

查看与设置
SELECT NOW(), UTC_TIMESTAMP(), @@global.time_zone, @@session.time_zone;   # 对比本地时间与 UTC 时间
SET GLOBAL time_zone = '+08:00';      # 新连接生效
SET time_zone = '+08:00';             # 仅当前会话
SELECT @@system_time_zone;            # 操作系统时区,作为参考
SHOW VARIABLES LIKE 'time_zone';      # 交叉验证当前取值

加载时区表与持久化配置

加载时区表与持久化配置
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot -p mysql   # 导入时区表,命名时区才可用
# my.cnf 持久化:
# [mysqld]
# default-time-zone = '+08:00'
systemctl restart mysqld           # 或用 SET GLOBAL 临时生效,重启后按配置为准
mysql -e "SELECT @@global.time_zone, @@session.time_zone;"   # 变更后核对

两种时间类型对比

类型存储方式行为差异
TIMESTAMP底层存 UTC显示时按会话时区换算,取值范围到 2038 年
DATETIME原样存储不随会话时区变化,跨时区显示会出现偏差
CURRENT_TIMESTAMP 默认值写入时取当前时刻受会话时区影响
UNIX_TIMESTAMP()按会话时区解释字符串与时间戳互转时要确认时区
NOW()返回会话时区时间与 UTC_TIMESTAMP() 结果不同属正常

典型使用场景

  • 跨国业务统一按 UTC 存储,展示层再做本地化转换
  • 排查「时间差 8 小时」类问题,先核对会话时区
  • 数据迁移前后确认时区设置,避免时间字段整体偏移
  • 容器化部署时统一镜像与数据库时区配置
  • 日志与业务时间对不上,检查应用与数据库两侧时区
跨时区系统建议统一用 UTC 存储、在展示层转换;如果必须存本地时间,就统一用 DATETIME 并明确写入时区,不要两种类型混用。
修改时区后历史 TIMESTAMP 数据的显示会变化,但底层值并未改变;若把 DATETIME 与 TIMESTAMP 混在同一业务里,很容易出现难以解释的时间错位。

排错顺序

  • 先看系统时区与会话时区,确认差值来源是系统设置还是连接设置
  • 再核对应用连接初始化语句是否显式设置了时区
  • 最后确认时区表是否已加载,命名时区能否正常使用

易错点

  • 未加载时区表就设置命名时区:SET time_zone='Asia/Shanghai' 会报未知时区错误,只能先用固定偏移
  • 混用 DATETIME 与 TIMESTAMP:改时区后一部分字段变、一部分不变,排查成本很高
  • 只在会话级设置时区:连接池回收连接后设置失效,行为随连接漂移
  • 迁移时不看时区配置:数据导入后整体偏移若干小时,业务侧才发现

数据来源与参考

  • MySQL 8.0 Reference Manual: MySQL Server Time Zone Support

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌