关于Mysql6.0+的时区错乱问题

如果使用mysql6.0+的JDBC驱动版本的时候,有时候会出现程序时间与数据库时间相差很多个小时;

1.如果以北京时间为例,相差8个小时的情况一般是你在连接jdbc的url中没有标明system_time_zone=Asia/ShangHai,一般加上参数就可以解决;

2.如果以北京时间为例,相差13小时或者14个小时,大多数情况是mysql协商会话的时候,Java把服务器的 "CST" 时区 误以为是美国中部的 "CST" 时区;

 

关于 CST 时区, 用这个名字的并不是中国一个地区,其代表的含义有多个,所以是一个很混乱的时区;

美国中部时间 Central Standard Time (USA) UTC-06:00

澳大利亚中部时间 Central Standard Time (Australia) UTC+09:30

中国标准时 China Standard Time UTC+08:00

古巴标准时 Cuba Standard Time UTC-04:00

在美国中部时间的CST时区里面,因为实行冬令时和夏令时,夏令时为"3月11日至11月7日 ";

在夏令时的阶段,CST 为UTC-05:00, 和北京时间(UTC+08:00)相差13个小时;

在冬令时的阶段,CST 为UTC-06:00, 和北京时间(UTC+08:00)相差14个小时;

 

mysql新版本的时间协商,是在JDBC和mysql建立连接的时候查询的,在 com.mysql.cj.jdbc.ConnectionImpl 中的 initializePropsFromServer() 获取服务器时间的时候,如果time_zone为 "SYSTEM",的时候,会取一个mysql服务器的一个时间   system_time_zone ,这个可以在mysql中查到: show variables like '%time_zone%'; 

 

如果得到的是 CST ,Java程序里面就不能判断这是中国标准时间 CST +0800 ,会误以为这是美国中部标准时间 CST -0500,所以在转换相关时间格式的参数(如 timestamp Datetime 等等)时,会出错.

 
之前我们说我们用  Asia/Shanghai 时区,也就是UTC +08:00 ,即CST +0800,即说白了,我们服务器上现在是CST+0800 的时区,java程序误以为是CST-0500 的时区,所以导致时间相差13个小时,如果是冬令时,可能还会相差14个小时;
 
我们在使用 PreparedStatement 的参数填充时,如果你的时间字段就会出现此种情况,Timestamp的long类型数据会在  com.mysql.cj.jdbc.PreparedStatement.setTimestamp() 被加上时区做一次处理,所以到时和DateTime一样的问题;
 
解决方案:
  1.在mysql的配置文件中加入  default-time-zone = '+08:00' 

  2.登入服务器数据库,手动指定时区:

   set global time_zone = '+08:00'; 

   set time_zone = '+08:00'; 

  3.选择任何一种方案之后,重启数据库;

 

posted @ 2018-04-13 13:02  世间草木  阅读(1467)  评论(0编辑  收藏  举报