mysql时间与系统时间不一致的根本原因是系统时间不准或mysql未正确识别时区,需先校准系统时间并设置正确系统时区,再通过my.cnf配置default-time-zone='+08:00'(必须重启生效),同时jdbc连接串须显式指定servertimezone=asia/shanghai,并统一使用datetime类型避免timestamp的自动时区转换问题。

MySQL时间与系统时间不一致,根本不是数据库“自己走快/慢”,而是它照搬了错误的系统时间或没读对时区——先校准系统,再让MySQL认准这个时间。
查清系统时间和MySQL各自看到的时间
别猜,直接比对:
- 终端执行
date和timedatectl status,看系统当前时间与时区(Time zone行)是否是你期望的(如Asia/Shanghai) - 连上 MySQL 执行
SELECT NOW(), @@global.time_zone, @@session.time_zone; - 如果
NOW()和date差 8 小时,大概率是系统时区设成了UTC或 MySQL 没加载到正确偏移
改 MySQL 配置必须重启,且只认 default-time-zone
my.cnf 里写 time_zone = '+08:00' 是无效的——配置文件唯一合法项是 default-time-zone:
- 编辑
/etc/my.cnf或/etc/mysql/my.cnf,在[mysqld]段下加:default-time-zone = '+08:00'
- 别用
Asia/Shanghai,除非你已运行过mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql并确认SELECT COUNT(*) FROM mysql.time_zone_name;> 0 - 改完必须
systemctl restart mysqld,SET GLOBAL time_zone只临时生效,且不持久
JDBC 连接串漏掉 serverTimezone 就会双重转换
即使 MySQL 服务端设成 +08:00,JDBC 8.0+ 驱动默认仍按 JVM 本地时区解析时间:
- 连接串必须显式带:
?serverTimezone=Asia/Shanghai&useTimezone=true -
GMT%2B8在部分驱动中不识别,优先用 IANA 名称(Asia/Shanghai)或固定偏移(GMT%2B08) -
spring.jackson.time-zone对数据库层完全无效,别指望它能修正ResultSet.getTimestamp()的结果
Docker 环境里 /etc/localtime 缺失会导致 default-time-zone 静默失效
官方 MySQL 镜像默认不含 tzdata,default-time-zone = 'Asia/Shanghai' 会 fallback 到 SYSTEM,而容器内 /etc/localtime 常为空:
- 启动容器时挂载宿主机时区:
-v /etc/localtime:/etc/localtime:ro - 或构建镜像时安装 tzdata:
RUN apt-get update && apt-get install -y tzdata - 更稳妥的做法:容器内一律用
default-time-zone = '+08:00',它不依赖系统 tzdata 文件
真正容易被忽略的是 TIMESTAMP 字段——它存的是 UTC,读出来才按会话时区转;DATETIME 则完全不转。同一个字段,在 Navicat、Java 应用、命令行里查出的字面值可能完全不同,这不是 bug,是设计行为。











