MySQL 时区全解,如何修改数据库时区,JDBC 时区不一致时怎么办?

紧接上篇MySQL时区全解,date_time 和 timestamp 区别,GMT、UTC、CST、东八区分别指什么? ,我在里面分享了

  • datetimetimestamp的区别
  • CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP在创建表时的使用
  • GMT、UTC、CST、东八区相关科普,学习数据库时区和数据库服务器时区的控制参数

最后找出数据库时区是 CST ,但并非中国标准时间,导致存在异常,但没法解释我的问题,因为只有我的接口插入时间有问题。如果是数据库时区的原因,那所有插入的时间应该都存在问题。

在继续往下分享之前,先处理一个前面故意绕过的知识,修改数据库时区,前文我修改数据库时区的方法很简单粗暴

set time_zone='+08:00';

但这个设置只是临时的,而且只是会话级别,只要我们关闭这次数据库连接,重新进去,它的时区又变成原来的。

如果想更加深刻设置,用如下命令

set global time_zone = '+8:00';
flush privileges; 

这种修改属于全局修改,就算关闭连接重新进去,依然生效。但如果将数据库服务停止,再次启动,它的数据库时区又回到原来的。

如果想永久修改,要修改配置文件 my.cnf(linux),在 [mysqld] 节下增加 default-time-zone = ‘+08:00’。这种修改就算重启数据库服务也能生效。

这种修改效力很强大,但还不是最强的,优先级最高的是 JDBC 配置的时区。

serverTimezone=Asia/Shanghai

只要在这配置时区,那上面所有设置都不会生效,以 JDBC 的时区为准。

比如我将数据库时区修改成 GMT+0 标准时间

set global time_zone = '+00:00';
flush privileges;

image-20211116202710901

然后再用 JDBC 东八区时间(中国标准时间)去插入时间

serverTimezone=Asia/Shanghai

Java 代码如下

entity.setUpdateTime(new Date());
entity.setCreateTime(new Date());

插入到表里的时间还是东八区时间,也就是中国标准时间。比如现在是中国时间2021-11-16 20:24:02,表里的时间也是这个值。

但这里有点特殊情况特别要注意,这里的时间是我们用代码通过 JDBC 插入的,如果我们不生成时间向表里插入呢?

比如将上面两行代码注释,因为表里字段都用了默认时间设置CURRENT_TIMESTAMP,所以就算没传值,数据库还是会给我们自动生成一个当前默认时间,但这里生成的时间就是按照数据库时区生成的,因为数据库是 GMT+0 时区,这里会变成2021-11-16 12:24:02,这就和中国时间相差 8 小时了。

很明显,找到我的问题,我插入时间时并没手动在代码生成插入,而是数据库自动生成的。根据上篇博客中提到的,虽然都是 CST ,但中国和美国之间相差 13 个小时。

中国标准时间 China Standard Time UTC+08:00
美国中部时间 Central Standard Time (USA) UTC-05:00 / UTC-06:00

现在来做个总结:

1、JDBC 时区和数据库时区一定要一致

2、表里时间可以配置默认值CURRENT_TIMESTAMP,避免因为极端情况导致时间是 null,程序崩溃,但时间一定要通过 JDBC 插入,不能依赖数据库自动生成。

3、根据阿里规范,可以将createTimeupdateTime放到基类,然后直接默认获取当前时间,这样可以避免忘记。

本文由老郭种树原创,转载请注明:https://guozh.net/mysql-time-zone-2/

发表回复

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