Java数据库查询时间比数据库存储时间多14个小时

Java数据库查询时间比数据库存储时间多14个小时

今天工作中遇到了遇到了Java数据库查询时间比数据库存储时间多14个小时这个问题,简单的说就是数据库存储的是1点,但是通过Mybatis
查询出来的时间却是15点。根据经验这种问题一般都是某个地方时区设置的不对导致的。
因此首先从MySQL安装的机器排查,在机器上执行date命令发现时间是对的。这样的话,基本可以确定是某处代码的时区弄错了。
首先检查数据库的jdbc 连接参数,发现没有设置时区相关的参数,对应的java pojo的对应字段上也没有标注时区相关的注解。
因此只能怀疑所使用的mysql驱动中的时区处理问题了。我们工程使用的mysql连接jar如下:

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
                <version>6.0.6</version>
            </dependency>

经过一番代码调试,最终在com.mysql.cj.jdbc.io.JdbcTimestampValueFactorycreateFromTimestamp方法,
发现mysql的底层驱动程序对从数据库查询出来的时间用了一个Calender做类型转换,Calender记录中包含的时区为CST
跟中国的时区Asia/Shanghai正好差了14小时。
那么为什么mybatis连接数据库会使用CST的美国时间呢?继续查看源码发现
mysql连接数据库的时候会从mysql读取系统的时区设置,调试com.mysql.cj.mysqla.MysqlaSession.javaconfigureTimezone方法发现,
this.getServerVariable("system_time_zone")从系统里面读出来的时区设置是CST,至此问题已经清楚了,是mysql设置的时区不对。

解决办法1

+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)
mysql> set global time_zone = '+8:00';
Query OK, 0 rows affected (0.00 sec)
mysql> set time_zone = '+8:00';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> exit

修改mysql时区后要重启自己的服务日期生效。

解决办法2

有时候dba不同意修改数据库的市区,那么可以通过在jdbc url上面加serverTimezone参数。可以选择东8区的Hongkong、Asia/Shanghai或者Asia/Hongkong作为参数,修改后url为

jdbc:mysql://xxx.0.15:3306/xxx?characterEncoding=utf-8&&allowMultiQueries=true&useSSL=false&serverTimezone=Hongkong

然后重启应用就好了。

参考资料

本文版权归作者所有,禁止一切形式的转载,复制等操作
赞赏

微信赞赏支付宝赞赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注