情况
Spring Boot 连接 MySQL8.0.16 报错。
错误日志信息
Spring Boot 使用 Mybatis 连接 MySQL 的详细错误日志:
Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Error: GlobalConfigUtils setMetaData Fail ! Cause:java.sql.SQLException: The server time zone value ‘�й���ʱ��’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
出现原因
抛出异常是因为MySql服务器时区(继承自系统时区)的格式与mysql连接器所期望的格式不同。
解决办法
1.降低mysql-connector-java
依赖版本
在我看来不建议,既然升级了数据库版本,数据库连接驱动自然要升级,更改好对应配置即可。
不过,降低版本的确可以解决这个问题,使用5.1.x
版本即可。
而6.0.x
及以上版本还会有Unable to load authentication plugin 'caching_sha2_password'
的问题,这里就细说,也不选择了。
示例:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
2.JDBC配置中增加mysql连接时区配置
在JDBC连接url后添加时区属性:serverTimezone=UTC
,其中UTC是统一标准世界时间。
但是,serverTimezone=UTC
这样设置的时区默认为0,而中国在东八区,通过这个配置写入到数据库的日期数据查看慢8到14个小时,会显得很诡异。
尽管在Java代码中可以指定时区去获取正确的时间,但平常在查看数据库的时候会误导信息查询。
所以,需要指定为中国时区的话,可以将配置修改为serverTimezone=GMT%2B8
。
具体配置如下:
jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
延伸
关于时区:
- UTC,即协调世界时。UTC是以原子时秒长为基础,在时刻上尽量接近于GMT的一种时间计量系统。为确保UTC与GMT相差不会超过0.9秒,在有需要的情况下会在UTC内加上正或负闰秒。UTC现在作为世界标准时间使用。
- GMT:即格林尼治标准时间,也就是世界时。GMT的正午是指当太阳横穿格林尼治子午线(本初子午线)时的时间。但由于地球自转不均匀不规则,导致GMT不精确,现在已经不再作为世界标准时间使用。
UTC与GMT基本上等同,误差不超过0.9秒。
关于MySQL支持的时区:
通过mysql-connector-java
源码中com.mysql.cj.util.TimeUtil
类的TIME_ZONE_MAPPINGS_RESOURCE
属性,可以看到serverTimezone支持的相关设置在/com/mysql/cj/util/TimeZoneMapping.properties
文件中。
找到/com/mysql/cj/util/TimeZoneMapping.properties
文件,其中支持的时区内容如下:
#Windows Zones
#Mon Apr 24 23:22:45 WEST 2017
AUS\ Central\ Daylight\ Time=Australia/Darwin
AUS\ Central\ Standard\ Time=Australia/Darwin
AUS\ Eastern\ Daylight\ Time=Australia/Sydney
AUS\ Eastern\ Standard\ Time=Australia/Sydney
Afghanistan\ Daylight\ Time=Asia/Kabul
Afghanistan\ Standard\ Time=Asia/Kabul
Alaskan\ Daylight\ Time=America/Anchorage
Alaskan\ Standard\ Time=America/Anchorage
Aleutian\ Daylight\ Time=America/Adak
Aleutian\ Standard\ Time=America/Adak
Altai\ Daylight\ Time=Asia/Barnaul
Altai\ Standard\ Time=Asia/Barnaul
Arab\ Daylight\ Time=Asia/Riyadh
Arab\ Standard\ Time=Asia/Riyadh
Arabian\ Daylight\ Time=Asia/Dubai
Arabian\ Standard\ Time=Asia/Dubai
Arabic\ Daylight\ Time=Asia/Baghdad
Arabic\ Standard\ Time=Asia/Baghdad
Argentina\ Daylight\ Time=America/Buenos_Aires
Argentina\ Standard\ Time=America/Buenos_Aires
Astrakhan\ Daylight\ Time=Europe/Astr