解决MariaDB/MySQL保存时间少了14个小时

发布于 2018-12-18  3 次阅读


这是一个坑,遇到了随手记录一下:

问题描述:

使用JPA自动保存了带有Date字段(数据库中是Timestamp类型)的数据到MariaDB数据库中,发现保存的时间正好少了14个小时。

先注意一下这个关键的数值14。一般来说我们可能会遇到时间少了8个小时,对这些数字比较敏感就能瞬间反应过来,啊是不是时区不对。
众所周知我们使用的是东八区的时间,即UTC+8也可作GMT+8(GMT和UTC的概念是一样的,都是指的伦敦皇家格林尼治天文台的标准时间)。一般来说是程序或系统的时间设置有问题,默认的是格林尼治时间,即GMT+0,所以如果少了8个小时,我们便能很快地反应出来,啊,需要修改时间。
可是这次时间少的有点怪了,少了14个小时。其实换算一下,就是GMT-6西六区,也就是美国中部时间(CST)

可以看到这里就是坑的根源所在
>
美国中部时间 CST:Central Standard Time (USA) UTC-6:00
澳大利亚中部时间 CST:Central Standard Time (Australia) UTC+9:30
中国标准时间 CST:China Standard Time UTC+8:00
古巴标准时间 CST:Cuba Standard Time UTC-4:00

我们发现中国标准时间和美国中部时间的缩写居然是一致的。这就非常混乱了。查阅资料发现就是com.mysql.cj.jdbc 里的时区协商有问题。
当 JDBC 与 MySQL 开始建立连接时,会调用 com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer() 来获取服务器参数。其中 this.session.configureTimezone() 函数负责配置时区。而当其获取到MariaDB中的时区为CST时,就误以为是美国中部时间,设置成了UTC-6:00 自由的BUG(雾)。
因此我们就需要将MariaDB中的CST修改为准确的UTC+8:00来消除歧义。

进入数据库,输入命令如下:

MariaDB [(none)]>  show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)

MariaDB [(none)]> set global time_zone = '+8:00';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> set time_zone = '+8:00';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.03 sec)

MariaDB [(none)]> Ctrl-C -- exit!

截图如下
MariaDB修改时区
截图里面第一次手误打成了'+8.00',正确的应该是:

另外还发现这个属性好像会因为数据库重新启动而恢复默认值CST,我们还可以在my.conf配置文件里面修改。
[mysqld]节点下新增如下配置项

default-time-zone='+8:00'

然后重启数据库

systemctl restart mariadb.service

OK,踩坑完毕。

Comments


来自像素世界的代码家,创造第九艺术!