当前时区是否为SYSTEM或UTC需执行SELECT @@global.time_zone, @@session.time_zone;验证:若返回SYSTEM则跟随系统时区,若为+00:00或UTC则比北京时间慢8小时;再用SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);确认差值应为08:00:00。
确认当前时区是否真为SYSTEM或UTC
很多问题其实不是“没设”,而是设了但没生效,或者误以为已生效。先连上 MySQL 执行:
。如果返回
,说明 MySQL 正在跟随系统时区;若返回
或
,则默认就是 UTC——这正是北京时间(
)慢 8 小时的根源。
再补查一句:
。理想结果应是
;如果返回
,说明 NOW() 实际输出的是 UTC 时间,时区根本没切过来。
永久生效必须改 my.cnf / my.ini 的 [
mysql
d] 段
是唯一能保证服务重启后仍为
的配置项,它作用于全局且优先级高于系统时区。临时 SET 不写入配置文件,重启即丢。
编辑配置文件(Linux 通常为
或
;Windows 多为
),在
下新增一行:
注意:
不能写成
或
;值必须带引号、用
格式(不要写
或
);修改后必须重启服务:
(Linux)或通过服务管理器重启(Windows)。
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
SET GLOBAL time_zone 只影响新连接,且权限受限
执行
后,现有连接的
不变,只有后续新建连接才会继承这个全局值。它适合紧急测试,但不可替代配置文件。
常见报错:
。这意味着当前用户没有足够权限——普通应用账号几乎都不该有此权限,别硬加,直接走配置文件更安全可靠。
只影响当前会话,退出即失效
需要高权限,且不持久
这类命名时区需提前导入时区表(
),否则报错 1298,没必要折腾
TIMESTAMP 和 DATETIME 的行为差异必须同步理解
即使时区设对了,
字段仍会自动按当前会话时区做转换(存 UTC,读本地时区),而
始终原样存储、不转换。如果你的应用依赖
或
自动填充,并希望字段值直接对应北京时间,那必须确保:
是
,且建表时明确用
——否则可能在跨时区客户端读出来的时间“看起来对”,实则底层已错位。
最容易被忽略的一点:JDBC 连接串里若显式写了
,会覆盖 MySQL 服务端设置,导致
解析出错。此时必须同步改成
或
。
SELECT @@global.time_zone, @@session.time_zone;SYSTEM+00:00UTC+08:00SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);08:00:0000:00:00default-time-zone+08:00/etc/my.cnf/etc/mysql/my.cnfC:\ProgramData\MySQL\MySQL Server 8.0\my.ini[mysqld]default-time-zone = '+08:00'default-time-zonetime-zonetimezone+08:00+8:00CSTsystemctl restart mysqldSET GLOBAL time_zone = '+08:00';@@session.time_zoneERROR 1227 (42501): Access denied; you need (at least one of) the SYSTEM_VARIABLES_ADMIN privilege(s) for this operationSET time_zone = '+08:00';SET GLOBAL time_zoneasia/shanghaimysql_tzinfo_to_sqlTIMESTAMPDATETIMENOW()CURRENT_TIMESTAMP@@session.time_zone+08:00TIMESTAMP DEFAULT CURRENT_TIMESTAMPserverTimezone=UTCTIMESTAMPserverTimezone=GMT%2B8serverTimezone=Asia/Shanghai