跨时区业务中,global time_zone必须显式设为'+08:00'而非SYSTEM,因SYSTEM冻结启动时系统时区快照,云环境或容器中系统时区可能被静默修改(如切至UTC),导致新连接的NOW()、TIMESTAMP读写突变8小时且无法SQL修复。

直接说结论:跨时区业务中,global time_zone 必须显式设为固定偏移量(如 '+08:00')或命名时区(如 'Asia/Shanghai'),绝不能留默认的 SYSTEM。
为什么不能用 SYSTEM?
SYSTEM 表示 MySQL 启动时读一次操作系统时区,之后就“冻结”在那个快照里。但问题在于:云服务器、容器镜像、自动化运维脚本经常悄悄改系统时区(比如统一设为 UTC),而你根本不会收到通知。一旦发生,所有新连接的 NOW()、CURRENT_TIMESTAMP、TIMESTAMP 字段读写行为全都会突变,且无法通过 SQL 修复——因为 @@system_time_zone 是只读的。
- 查证方式:
SELECT @@global.time_zone, @@system_time_zone;—— 如果两者值不同,说明global已被手动改过;如果相同且是SYSTEM,那就处于高风险状态 - 典型后果:订单时间集体漂移 8 小时、定时任务执行窗口错位、主从之间
TIMESTAMP字段显示不一致
该设成 '+08:00' 还是 'Asia/Shanghai'?
优先选 '+08:00',除非你明确需要夏令时支持。
-
'+08:00':简单、稳定、无需额外加载时区表;适用于中国标准时间(CST)、新加坡、马来西亚等全年固定 UTC+8 的地区 -
'Asia/Shanghai':能正确处理历史夏令时(虽然中国已取消),但要求 MySQL 已导入 IANA 时区数据(需执行mysql_tzinfo_to_sql);若未导入,启动会报错或退化为SYSTEM - 绝对避免用
CST这类缩写——MySQL 会把它识别为美国中部时间(UTC-6),而不是中国标准时间(UTC+8),这是线上事故高频雷区
set global time_zone 后为什么老连接没变?
因为 global time_zone 只影响**新建立的连接**,已存在的连接继续使用自己建立时继承的 session.time_zone 值。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 验证当前连接实际生效的时区:
SELECT @@session.time_zone; - 临时修正单个连接:
SET time_zone = '+08:00';(注意:没GLOBAL关键字) - 生产环境修改后,必须让连接池滚动重建连接(比如重启应用、或配置连接池的
testOnBorrow+ 无效连接驱逐),否则旧连接会持续跑在错误时区下
和应用层 serverTimezone 必须对齐
MySQL 的 global time_zone 和 JDBC 连接串里的 serverTimezone 是两套独立配置,但必须语义一致,否则 TIMESTAMP 字段会出现双重转换。
- 如果 MySQL
global time_zone是'+08:00',JDBC 连接串必须写serverTimezone=GMT%2B8或serverTimezone=Asia/Shanghai(不能写UTC或空) - 如果连的是 RDS 或托管服务,有些平台会屏蔽
SET GLOBAL权限,此时只能靠连接串参数兜底,global time_zone实际失效 - DATETIME 字段不受
time_zone影响,所以如果你的应用大量使用DATETIME,那global time_zone配错只会导致函数返回值异常(如NOW()),不会污染字段值
最常被忽略的一点:即使你把 global time_zone 改对了,如果表里混用了 DATETIME 和 TIMESTAMP,它们对时区的反应完全不同——前者永远“所见即所存”,后者始终在做 UTC 转换。跨时区业务里,这个差异会放大成数据语义混乱,不是调一个参数就能抹平的。










