mysql全局时区必须设在my.cnf或my.ini的[mysqld]段中,通过default-time-zone='+08:00'配置并重启服务生效,写在其他段落无效,且不可用下划线命名或遗漏等号。

MySQL全局时区设在哪?必须改my.cnf里的[mysqld]段
MySQL没有“数据库级”时区,只有服务器全局和会话两级。想让所有新连接默认用东八区,唯一可靠方式是修改配置文件——不是my.ini(Windows旧版),也不是/etc/mysql/conf.d/下某个碎片配置,而是主配置文件中明确的[mysqld]段。
-
default-time-zone必须写在[mysqld]里,写在[client]或[mysql]段完全无效 - 推荐用偏移量:
default-time-zone = '+08:00',避免依赖系统tzdata包和MySQL时区表是否已导入 - 如果坚持用
Asia/Shanghai,得先确认mysql.time_zone表有数据:运行mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql,否则启动报错或回退到SYSTEM - 改完必须重启
mysqld,systemctl restart mysql或service mysqld restart,仅flush privileges不生效
SELECT NOW()还是错?检查@@global.time_zone和@@session.time_zone是否一致
即使my.cnf改了、服务也重启了,SELECT NOW()仍可能显示UTC时间——因为客户端连接时被驱动覆盖了会话时区。
- 先查真实状态:
SELECT @@global.time_zone, @@session.time_zone;,两个都应返回+08:00才算生效 - 如果
@@global对但@@session是SYSTEM或UTC,说明应用连接字符串里显式指定了时区,比如JDBC加了serverTimezone=GMT%2B8,而这个参数值和MySQL实际配置冲突 - PHP PDO、Python PyMySQL等也类似:连接后第一句执行
SET time_zone = '+08:00'比依赖全局设置更可控 -
system_time_zone只是只读参考值,它反映OS时区,不能动,也不影响MySQL行为
为什么TIMESTAMP字段时间对,DATETIME却差8小时?
这不是配置错误,是MySQL设计使然:TIMESTAMP存的是UTC时间,读取时自动按会话时区转换;DATETIME存什么就是什么,不做任何转换。
- 如果你用
DATETIME存“2026-08-11 14:10:00”,而会话时区是UTC,那它就真代表UTC时间,显示出来就是凌晨6点 - 跨时区业务强烈建议统一用
TIMESTAMP+ 全局设UTC,应用层存入前转UTC、展示前转本地——而不是靠MySQL“帮你转” - 别信
CONVERT_TZ()能救场:它需要时区表完整,且每次调用都额外计算,性能敏感场景慎用 - 开发环境常把
time_zone设成SYSTEM,上线前务必改成固定偏移量,否则测试通过、生产翻车
重启MySQL后@@global.time_zone仍是SYSTEM?配置文件路径或语法错了
常见假成功:以为改了配置,其实MySQL根本没加载到那行。
- 用
mysqld --help --verbose | grep "default"确认MySQL实际加载的配置文件路径,很多Docker镜像或源码编译版默认读/usr/my.cnf而非/etc/my.cnf -
default-time-zone不能写成default_time_zone(下划线),也不能漏掉=号,空格不能多也不能少 - 配置文件里如果有
!includedir,确保你的修改不在被覆盖的子配置里;优先把default-time-zone直接写进主[mysqld]段顶部 - 启动时加
--print-defaults看MySQL解析出的最终参数,比猜更准
TIMESTAMP和DATETIME混用、应用层又手动SET time_zone时,问题会藏得很深。











