今天生产插入数据的时候发现数据库时间不对劲,时间慢了八小时
一开始怀疑服务器上的时间不对,于是跑去检查了下服务器上时间和时区
date
date -R
发现没问题
继续排查是否是代码的问题
找到插入数据库时间代码
xxx.setCreateTime(LocalDateTime.now());
正常,本地测试没问题,本地mysql数据库时间显示正常
思考了下,既然代码和服务器时间都没问题,于是检查生产mysql数据库时区
查看mysql当前时间,当前时区
SELECT NOW();
show variables like '%time_zone%';
生产数据库时区
time_zone说明mysql使用system的时区,system_time_zone说明system使用CST时区
本地数据库时区
发现生产数据库时区是UTC,而我本地的是CST,会不会跟这个有关系,继续进一步深挖
看了下jdbc连接的url中配置的时区参数(我用的数据库版本是mysql8.0
以上的)
没错啊,&serverTimezone=GMT%2B8
,是东八区啊,很奇怪
UTC代表的是
全球标准时间
,但是我们使用的时间是北京时区也就是东八区,领先UTC八个小时。mysql 使用了UTC方式来记录日志时间,也就是说这是个世界统一时间,存入mysql中的时间只能是UTC时间。mysql的timestamp类型数据,存储的时候会转化成UTC时间戳,读取时再从UTC转化为本地时间戳。各地的标准时间为格林威治时间(G.M.T)加上 (+) 或减去 (-) 时区中所标的小时和分钟数时差。中国是GMT+8
.
根据这个信息,我的解决办法:
CTT - Asia/Shanghai,在jdbc的连接里使用&serverTimezone=CTT
最后重新启动应用
docker stop 容器ID
docker start 容器ID
ok,没问题,可以正确的插入时间
java.time.ZoneId类的帮助文档和源码定义了时区
- EST - -05:00
- HST - -10:00
- MST - -07:00
- ACT - Australia/Darwin
- AET - Australia/Sydney
- AGT - America/Argentina/Buenos_Aires
- ART - Africa/Cairo
- AST - America/Anchorage
- BET - America/Sao_Paulo
- BST - Asia/Dhaka
- CAT - Africa/Harare
- CNT - America/St_Johns
- CST - America/Chicago
- CTT - Asia/Shanghai
- EAT - Africa/Addis_Ababa
- ECT - Europe/Paris
- IET - America/Indiana/Indianapolis
- IST - Asia/Kolkata
- JST - Asia/Tokyo
- MIT - Pacific/Apia
- NET - Asia/Yerevan
- NST - Pacific/Auckland
- PLT - Asia/Karachi
- PNT - America/Phoenix
- PRT - America/Puerto_Rico
- PST - America/Los_Angeles
- SST - Pacific/Guadalcanal
- VST - Asia/Ho_Chi_Minh
---------------------------------更新2024-11-20---------------------------------
查看new Date()是否少了8小时,如果是,应该是jvm的时间少了8小时,通过以下方式解决;
第1方法不生效,第2方法成功解决:
1、查看时区文件/etc/localtime
执行 ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime命令修改时区
2、添加启动参数-Duser.timezone=GMT+08
java -jar -Duser.timezone=GMT+08 demo.jar --server.port=8080
参考:SpringBoot服务时间与linux服务器时间相差8小时
如果new Date()时间是对的,那么就有可能是数据库连接的问题,通过数据库url添加serverTimezone=GMT%2B8解决
注意:本文归作者所有,未经作者允许,不得转载