MySQL JDBC驱动程序5.1.33-时区问题


359

一些背景:

我在Tomcat 7上运行了Java 1.6 webapp。数据库是MySQL 5.5。以前,我使用Mysql JDBC驱动程序5.1.23连接到数据库。一切正常。我最近升级到Mysql JDBC驱动程序5.1.33。升级后,Tomcat将在启动应用程序时引发此错误。

WARNING: Unexpected exception resolving reference
java.sql.SQLException: The server timezone value 'UTC' is unrecognized or represents more than one timezone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc timezone value if you want to utilize timezone support.

为什么会这样呢?


1
您的JDBC URL是什么样的?
David Levesque 2014年

检查我的答案stackoverflow.com/a/44720416/4592448。我认为这是最好的答案)
Fortran

Answers:


673

显然,要使MySQL JDBC驱动程序的5.1.33版与UTC时区一起使用,必须serverTimezone在连接字符串中显式指定。

jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

4
根据文档,当使用useLegacyDatetimeCode = false时,useJDBCCompliantTimezoneShift无效。因此,这里并不需要...
matof

24
这解决了我的错误。附加说明,用&amp;转义&。在persistence.xml文件中:<属性名称=“ javax.persistence.jdbc.url” value =“ jdbc:mysql:// localhost / test?useUnicode = true&amp; useJDBCCompliantTimezoneShift = true&amp; useLegacyDatetimeCode = false&amp; serverTimezone = UTC” />
pdem '16

5
那是不对的。useLegacyDatetimeCode = false的点是不必指定serverTimezone,因此客户端可以更正时区差异。这是该版本的MySQL客户端中的错误。
antgar9年

2
该解决方案破坏了除GMT以外的时区。我认为正确的解决方案在下面
DuncanSungWKim'Dec 13'17

1
解决方案适用于8.0.17。发生了新的MySQL安装。不能相信这个错误在这么多年之后还没有得到修复。
Tilman Hausherr

101

我已经通过配置MySQL解决了这个问题。

SET GLOBAL time_zone = '+3:00';


6
如果您使用的是MSK时区,则为+3,则可以使用以下作为数据库地址:jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Europe/Moscow。看起来mysql-connector无法识别短时区名称。
babay

2
当夏令时改变时钟时,您会怎么做?
isapir '18 -10-8

3
在mysql 8.0中,您可以调用“ setpersist time_zone ='+00:00';” 将其永久设置为UTC,而无需编辑my.cnf或重新启动服务器。见mysqlserverteam.com/…–
ccleve

如果通过唯一的手动SQL查询进行设置,则此设置将恢复为数据库重新启动后的原始值。
CBA110

确实有效-记得修改本地时区字符串,以代替+3 SET GLOBAL time_zone ='+3:00';
Pravin

61

在阅读了有关该主题的几篇文章之后,测试了不同的配置,并基于我所了解的来自该mysql bug线程的一些见解:

  • 服务器时区尤其重要,这对于将数据库中存储的日期转换为应用程序服务器的时区非常重要。还有其他含义,但这是最明显的一个
  • GMT x UTC时区系统。GMT诞生于19世纪后期,可以在标准时间和夏季时间之间切换。此属性可能导致数据库服务器转换为夏季时间,而应用程序没有注意到它的情况(也许还有其他复杂情况,但我没有进一步研究)。UTC不会随时间变化(在0度经度处,它始终在平均太阳时间的1秒钟之内)。
  • 前面的mysql jdbc连接器版本5.1中引入了serverTimeZone定义。直到版本8为止,可以使用忽略useLegacyDatetimeCode=true它,与结合使用useJDBCCompliantTimezoneShift=true将使应用程序获得每个连接上的数据库时区。在这种模式下,GMT时区(例如“英国夏令时”)将转换为内部java / JDBC格式。可以在.properties文件(例如文件)中定义新时区
  • 从jdbc驱动程序版本8开始,删除了自动时间匹配(useJDBCCompliantTimezoneShift)和旧版时间格式(useLegacyDatetimeCode)(请参见mysql jdbc连接器changelog)。因此设置这两个参数无效,因为它们会被完全忽略(新的默认值为useLegacyDateTimeCode=false
  • 以这种方式设置serverTimezone成为强制性的,如果任何时区(应用/数据库服务器)中的格式不是“UTC + XX”或“GMT + XX”
  • 将服务器时间设置为UTC不会产生影响(例如,使用jdbc:mysql://localhost:3306/myschema?serverTimezone=UTC,即使您的应用程序/数据库服务器不在此时区中也是如此。重要的是应用程序连接字符串+数据库要与相同时区同步。 ,只需将serverTimezone = UTC设置为数据库服务器上的其他时区,即可转换从数据库中提取的所有日期
  • MySQL的默认时区可以设置为UTC + 0与的my.ini或my.cnf中文件(Windows / Linux的分别地)通过将线default-time-zone='+00:00'(在细节这个StackOverflow的交
  • 自动为AWS(amazon Web服务)上配置的数据库分配UTC + 0默认时间(请参阅此处的AWS帮助页面

1
好的答案,谢谢。各种项目符号都很有用。我接受了将a default-time-zone = '+00:00'放入自制/usr/local/etc/my.cnf文件的建议。看来,周围的空格=很重要,因此您可以编辑该项目符号以包含它们。
Mark Edington

51

如果您正在使用Maven,你可以设置另一个MySQL连接器版本(我有同样的错误,所以我改变了从6.0.2到39年1月5日)在pom.xml

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.39</version>
</dependency>

如另一个答案中所述,此问题已在6.0.3或更高版本中修复,因此您可以使用更新的版本:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>6.0.3</version>
</dependency>

保存pom.xml文件后,Maven将自动重新构建项目。


2
对于那些下载了mysql-connector-java / 6->的人,只需下载例如mysql-connector-java / 5.1.20,它应该可以工作。谢谢!
合并

6
应避免降级。此外,它还没有固定6.0.6。更好地使用上述解决方案
phil294

即使使用最新的jar,我也遇到相同的错误[mysql-connector-java-6.0.5.jar:6.0.5]
user2478236

18
我什至在8.0.12-
罗伯特·尼斯特罗伊

13
8.0.13给出了相同的错误。5.1.47但是对我有用。
本地主机

36

连接字符串应如下设置:

jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

如果要定义在连接xml文件(如persistence.xmlstandalone-full.xml等..),而不是&你应该使用&amp;或使用CDATA块。


1
那是不对的。useLegacyDatetimeCode = false的点是不必指定serverTimezone,因此客户端可以更正时区差异。
antgar9年

这对我使用phpStorm 2019.1.4连接到MySQL 5.7很有用。
moult86

29

从版本5.1.33到5.1.37,这是mysql-connector-java中的错误。我在这里报告过:http : //bugs.mysql.com/bug.php?id=79343

编辑:此问题已从mysql-connector-java 5.1.39中更正。

这是loadTimeZoneMappings方法中TimeUtil类中的一个错字,引发了NPE定位/com/mysql/jdbc/TimeZoneMapping.properties文件。如果查看代码,则文件应位于TimeUtil类加载器中,而不是TimeZone中:

TimeUtil.class.getResourceAsStream(TIME_ZONE_MAPPINGS_RESOURCE);

参数useLegacyDatetimeCode可以在使用日期时自动更正客户端和服务器时区之间的差异。因此,它可以帮助您精确地不必在每个部分中指定时区。尽管使用serverTimeZone参数是一种解决方法,并且同时发布了补丁,但是您可以像我一样尝试更好地自己更正代码。

  • 如果是独立应用程序,则可以尝试将更正后的com / mysql / jdbc / TimeUtil类添加到代码中,并小心执行jar加载顺序。这可以帮助: https //owenou.com/2010/07/20/patching-with-class-shadowing-and-maven.html

  • 如果是Web应用程序,则更简单的解决方案是创建您自己的mysql-connector-java-5.1.37-patched.jar,将.class直接替换为原始jar。


亲爱的,感谢您的举报。很高兴有人能够确定该错误。您知道修复程序何时发布吗?
bluecollarcoder

您建议的解决方案很棒,但是我认为修改驱动程序源和管理Maven依赖关系对于大多数人来说可能太烦人了。
bluecollarcoder

4
@Gili这是不固定的版本6.0.6的
Imme22009

6
该错误尚存在于8.0.11
约翰·利特尔,时间

3
@JohnLittle我在8.0.15中也遇到了这个问题,但是它不再是由错误引起的。时区已正确加载,但是CET和CEST(这些时区给我带来了麻烦)未包含在TimeZone.getAvailableIDs()或中,TimeZoneMapping.properties因此此解决方案在这里无济于事。解决方案可能设置为serverTimezone=Europe/Berlin
JPT

29

我解决了将连接字符串放在URL下方的问题

jdbc:mysql://localhost:3306/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

1
那是不对的。useLegacyDatetimeCode = false的点是不必指定serverTimezone,因此客户端可以更正时区差异。
antgar9 '19

25

只需在application.properties上添加serverTimeZone = UTC即可。
spring.datasource.url=jdbc:mysql://localhost/db?serverTimezone=UTC


22
  1. 我在[mysqld]部分的mysql配置文件中添加了

    default_time_zone='+03:00'
  2. 并重启mysql服务器:

    sudo service mysql restart

哪里+03:00我的UTC时区。

我的OS ubuntu 16.04上的配置文件路径:

/etc/mysql/mysql.conf.d/mysqld.cnf

警告:如果您的时区有夏季和冬季。如果更改时间,则必须在配置中更改UTC。一年两次(通常),或使用SUDO设置CRONTAB。

我的网址jdbc连接:

"jdbc:mysql://localhost/java"

1
几乎在所有生产用例中,必须重新启动Mysql基本上都是无法启动的。涉及复制时,这甚至成为一个问题。
bluecollarcoder

@bluecollarcoder仅需要在[mysqld]部分添加。如果没有[mysqld]部分,则添加该部分。示例我的配置pastebin.com/j4F7t2KS
Fortran

1
我将Linux服务器的/ etc / localtime从/ usr / share / zoneinfo / US / Pacific更新到了/ usr / share / zoneinfo / America / Los_Angeles,然后重新启动了mysql服务,这为我解决了这个问题。
vinnyjames,

就我提供的语法而言,重新启动时出现错误,正确的语法是:default-time-zone='+03:00'相反,根据此答案。也来自DBeaver。
wscourge

如果您必须告诉公司中的每个开发人员更改其MySQL配置
不适当

16

我有同样的问题,我解决了它,仅将“?serverTimezone = UTC”附加到我的字符串连接中。

sinossi我的问题:

java.sql.SQLException:服务器时区值“ CEST”无法识别或代表多个时区。如果要利用时区支持,则必须配置服务器或JDBC驱动程序(通过serverTimezone配置属性)以使用更特定的时区值。

my dbDriver = com.mysql.jdbc.Driver

my jar = mysql-connector-java-8.0.12.jar

my java = 1.8

my tomcat = Apache Tomcat Version 8.5.32

my MySql server = MySql ver.8.0.12 



13

解决问题所需的一切serverTimezone

String url = "jdbc:mysql://localhost:3306/db?serverTimezone=" + TimeZone.getDefault().getID()

最新的5.4.15版本也发生在我身上。但是,固定的:加入“serverTimezone =?” + TimeZone.getDefault()的getID()”旁边的乌尔数据库,解决了问题。
维护设备

10

您可以在Maven依赖项中使用MySQL连接器,

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.14</version>
</dependency>

然后,您需要在application.properties文件中设置正确的参数,

spring.datasource.url=jdbc:mysql://localhost:3306/UserReward?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=testuser
spring.datasource.password=testpassword
# MySQL driver
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect

9

我正在使用mysql-connector-java-8.0.13并遇到相同的问题。我在命令行控制台中创建了数据库,并通过在命令行上使用@Dimitry Rud的解决方案解决了此问题:

SET GLOBAL time_zone = '-6:00';

我不需要重新启动任何东西,设置时间并立即在eclipse中运行我的代码,它没有任何问题。

该错误应该在较旧的版本中修复,但是我认为我收到此错误是因为在控制台中创建数据库之后,我没有进行设置。我没有使用工作台,也没有使用其他应用程序而不是控制台来管理它。


6

在mysql工作台上运行以下sql语句:

  1. SET @@ global.time_zone ='+00:00';
  2. SET @@ session.time_zone ='+00:00';

使用以下sql语句检查是否设置了值:

选择@@ global.time_zone,@@ session.time_zone;


2
当有问题的错误在尝试从IntelliJ IDEA建立连接时弹出时,这对我有用。
Faheem Hassan Zunjani,

6

这对我有用。

在DBeaver 6.0上:转到连接设置>驱动程序属性>服务器时区>设置UTC。

另外,在spring boot config中,必须设置以下属性。

jdbc:mysql:// localhost:/?serverTimezone = UTC


5

显然,要使MySQL JDBC驱动程序的5.1.33版与UTC时区一起使用,必须在连接字符串中显式指定serverTimezone。

spring.datasource.url = jdbc:mysql://localhost:3306/quartz_demo?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

3

我在LibreOffice Base中也遇到了完全相同的问题。因此,我只是在连接字符串中指定了一个非“夏令时区”。
**在此处输入图片说明**

我尝试了没有使用“&serverTimezone = MST”,但是也失败了。

我还尝试了“&serverTimezone = MDT”,但失败了,因此由于某种原因,它不喜欢夏令时!


3

当我尝试在Windows上使用spring boot项目时,我遇到了同样的问题。

数据源网址应为:

spring.datasource.url=jdbc:mysql://localhost/database?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC


3

在查询下面运行到mysql DB以解决错误

MariaDB [xxx> SET @@global.time_zone = '+00:00';
Query OK, 0 rows affected (0.062 sec)

MariaDB [xxx]> SET @@session.time_zone = '+00:00';
Query OK, 0 rows affected (0.000 sec)

MariaDB [xxx]> SELECT @@global.time_zone, @@session.time_zone;

3

我遇到了类似于您的错误,但我的服务器时区值为'Afr。中央西部',所以我做了这些步骤:

MyError(在IntelliJ IDEA社区版上):

    InvalidConnectionAttributeException: The server time zone value 'Afr. centrale Ouest' 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 u....

当我将mysql服务器升级到SQL Server 8.0(MYSQL80)时,遇到了这个问题。

解决此问题的最简单方法是在MYSQL Workbench中编写以下命令-

  SET GLOBAL time_zone = '+1:00'

时区之后的值将等于GMT +/-时区中的差异。上面的示例适用于北非(GMT + 1:00)/或印度(GMT + 5:30)。它将解决问题。

在您的Mysql Workbench中输入以下代码并执行查询

[问题/源链接]

[答案的源链接]

[解决方案屏幕截图]


2
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/resultout? useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC","root",""))

这实际上是解决此问题的方法,但不仅是将其复制并粘贴到程序中。如果您仅阅读该行,则会发现“ resultout”,这是我的数据库的名称,您必须编写您的数据库。

字符串由三个部分组成,第一个是url,第二个是用户名,第三个是密码。在上一段中,我们清除了url。第二个和第三个String组件表示为您的用户名和密码,您必须相应地进行更改。

谢谢


1

我无需更改任何代码即可解决此问题。只需转到系统时间设置并设置时区即可。在我的情况下,默认时区为UTC,我将其更改为本地时区。重新启动所有服务后,一切都对我有用。


1

我来晚了,但是,如果您正在努力解决以下错误并使用数据源(javax.sql.DataSource):

The server time zone value 'CEST' is unrecognized or represents more than one time zone.

设置以下行以消除该错误:

MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setServerTimezone("UTC");

1

就我而言,这是一个测试环境,我必须使现有的应用程序能够在不进行任何配置更改的情况下工作,并且如果可能的话,也无需进行任何MySQL配置更改。我可以按照@vinnyjames的建议并将服务器时区更改为UTC来解决此问题:

ln -sf /usr/share/zoneinfo/UTC /etc/localtime
service mysqld restart

这样做足以解决我的问题。


1

我在/etc/mysql/my.cnf文件中添加了以下行:

default_time_zone='+00:00'

重新启动MySQL服务器:

systemctl restart mysql

它就像一种魅力。


0

同意@bluecollarcoder的答案,但是最好TimeZone.getDefault().getID();在连接字符串的末尾使用:

"jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=" + TimeZone.getDefault().getID();  

在这种情况下,Timezone参数会根据本地计算机时区自动更新。


那是不对的。useLegacyDatetimeCode = false的点是不必指定serverTimezone,因此客户端可以更正时区差异。
antgar9 '19

0

只需使用application.properties文件中的以下代码修改连接字符串。


spring.datasource.url=jdbc:mysql://localhost:3301/Db?
   useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=
   false&serverTimezone=UTC

0

将服务器时间设置为UTC不会产生影响(例如,使用 jdbc:mysql://localhost:3306/myschema?serverTimezone=UTC,即使您的应用程序/数据库服务器不在此时区中也是如此。重要的是应用程序连接字符串+数据库要与同一时区同步。

换句话说,只要serverTimezone=UTC在数据库服务器上设置一个不同的时区,就可以转换从数据库中提取的任何日期

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.