MySQL JDBC Driver 5.1.33 - Problema di fuso orario


361

Alcuni retroscena:

Ho una webapp Java 1.6 in esecuzione su Tomcat 7. Il database è MySQL 5.5. In precedenza, stavo usando il driver Mysql JDBC 5.1.23 per connettermi al DB. Tutto ha funzionato. Di recente ho eseguito l'aggiornamento al driver JDBC Mysql 5.1.33. Dopo l'aggiornamento, Tomcat genererà questo errore all'avvio dell'app.

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.

Perché sta succedendo?


1
Che aspetto ha il tuo URL JDBC?
David Levesque,

Controlla la mia risposta stackoverflow.com/a/44720416/4592448 . Penso che sia la migliore risposta)
Fortran,

Risposte:


675

Apparentemente, per far funzionare la versione 5.1.33 del driver MySQL JDBC con il fuso orario UTC, è necessario specificare serverTimezoneesplicitamente la stringa di connessione.

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

4
Secondo i documenti useJDBCCompliantTimezoneShift non ha alcun effetto quando si utilizza useLegacyDatetimeCode = false. Pertanto non è necessario lì ...
matof

24
Questo risolve il mio errore. Nota aggiuntiva, scappa da & con & amp; nel file persistence.xml: <nome proprietà = "javax.persistence.jdbc.url" valore = "jdbc: mysql: // localhost / test? useUnicode = true & amp; useJDBCCompliantTimezoneShift = true & amp; useLegacyDatetimeCode = false & amp; serverTime = UTT
pdem,

5
Non è corretto Il punto di utilizzoLegacyDatetimeCode = false non deve specificare serverTimezone, quindi il client corregge le differenze di fuso orario. È un bug in quella versione del client MySQL.
antgar9

2
Questa soluzione rovina il fuso orario tranne GMT. Penso che la soluzione giusta sia sottovalutata una sotto
DuncanSungWKim

1
la soluzione funziona con 8.0.17. È successo con una nuova installazione di MySQL. Non riesco a credere che questo errore non sia stato corretto dopo così tanti anni.
Tilman Hausherr,

101

Ho risolto questo problema configurando MySQL.

SET GLOBAL time_zone = '+3:00';


6
se si sta utilizzando MSK fuso orario è 3, allora si potrebbe utilizzare folowing come indirizzo db: jdbc:mysql://localhost/db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Europe/Moscow. Sembra che mysql-connettore non capisca i nomi brevi del fuso orario.
babay,

2
Cosa fai quando l'ora legale cambia l'orologio?
Isapir,

3
Con mysql 8.0 puoi chiamare "set persist time_zone = '+00: 00';" per impostarlo su UTC in modo persistente, senza la necessità di modificare my.cnf o riavviare il server. Vedi mysqlserverteam.com/…
ccleve

Se lo si imposta tramite una query SQL manuale univoca, questa impostazione ripristinerà il valore originale dopo il riavvio del DB.
CBA110,

funziona - ricorda di modificare la stringa del fuso orario locale al posto di +3 SET GLOBAL time_zone = '+3: 00';
Pravin

61

Dopo aver letto diversi post su questo argomento, testando diverse configurazioni e basato su alcune intuizioni di questo thread di bug mysql è quello che ho capito:

  • il fuso orario del server è importante in particolare per convertire le date memorizzate nel database nel fuso orario del server delle applicazioni. ci sono altre implicazioni, ma questa è la più evidente
  • GMT x sistemi di fuso orario UTC. GMT è stato concepito alla fine del XIX secolo e può essere spostato tra l'ora solare e l'ora legale. questa proprietà potrebbe portare a una situazione in cui il server del database passa all'ora legale e l'applicazione non se ne accorge (forse ci sono altre complicazioni ma non ho fatto ulteriori ricerche). L'UTC non varia nel tempo (è sempre entro circa 1 secondo dal tempo solare medio a 0 ° di longitudine).
  • La definizione serverTimeZone è stata introdotta nelle versioni mysql jdbc connettori 5.1. fino alla versione 8 potrebbe essere ignorato useLegacyDatetimeCode=true, che in combinazione con useJDBCCompliantTimezoneShift=truefarebbe sì che l'applicazione ottenga il fuso orario del database su ogni connessione. In questa modalità i fusi orari GMT come "British Summer Time" verrebbero convertiti nel formato java / JDBC interno. Nuovi fusi orari potrebbero essere definiti in un file .properties come questo
  • A partire dalla versione 8 del driver jdbc, sono stati rimossi la corrispondenza temporale automatica ( useJDBCCompliantTimezoneShift) e il formato ora legacy ( useLegacyDatetimeCode) ( consultare il log delle modifiche al connettore jdbc mysql ). pertanto l'impostazione di questi 2 parametri non ha alcun effetto poiché sono completamente ignorati (il nuovo valore predefinito èuseLegacyDateTimeCode=false )
  • In questo modo l'impostazione è serverTimezonediventata obbligatoria se uno qualsiasi dei fusi orari (server applicazioni / database) non è nel formato "UTC + xx" o "GMT + xx"
  • Non vi è alcun impatto sull'impostazione dell'ora del server come UTC (ad esempio jdbc:mysql://localhost:3306/myschema?serverTimezone=UTC, anche se i server delle applicazioni / del database non si trovano in questo fuso orario. L'importante è che la stringa di connessione dell'applicazione + il database siano sincronizzati con lo stesso fuso orario. In parole diverse , semplicemente impostando serverTimezone = UTC con un fuso orario diverso sul server del database si sposteranno tutte le date estratte dal database
  • Il fuso orario predefinito di MySQL può essere impostato su UTC + 0 con i file my.ini o my.cnf (rispettivamente windows / linux) aggiungendo la riga default-time-zone='+00:00'(dettagli in questo post StackOverflow )
  • Ai database configurati su AWS (servizi Web Amazon) viene assegnato automaticamente l'ora predefinita UTC + 0 ( vedere la pagina della guida di AWS qui )

1
Bella risposta, grazie. I vari proiettili sono tutti utili. Sono andato con il suggerimento di inserire un default-time-zone = '+00:00'nel /usr/local/etc/my.cnffile homebrew . Sembra che gli spazi intorno al =siano importanti anche se quindi potresti modificare quel proiettile per includerli.
Mark Edington,

51

Se stai usando Maven, puoi semplicemente impostare un'altra versione del connettore MySQL (ho avuto lo stesso errore, quindi sono passato dalla 6.0.2 alla 5.1.39) in pom.xml:

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

Come riportato in altre risposte, questo problema è stato risolto nelle versioni 6.0.3 o successive, quindi è possibile utilizzare la versione aggiornata:

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

Maven ricostruirà automaticamente il tuo progetto dopo aver salvato il pom.xmlfile.


2
Per coloro che hanno scaricato mysql-connettore-java / 6 -> basta scaricare ad esempio mysql-connettore-java / 5.1.20 e dovrebbe funzionare. Grazie!
Combina il

6
il downgrade dovrebbe essere evitato. inoltre, non è stato risolto con 6.0.6ancora. meglio usare la soluzione di cui sopra
phil294

sto ottenendo lo stesso errore anche con l'ultimo jar [mysql-connettore-java-6.0.5.jar: 6.0.5]
user2478236

18
Ho questo anche nell'8.0.12
Robert Niestroj il

13
8.0.13 dà lo stesso errore. 5.1.47 funziona per me comunque.
localhost

36

La stringa di connessione deve essere impostata in questo modo:

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

Se si definisce la connessione in un xmlfile (ad esempio persistence.xml, standalone-full.xml, ecc ..), invece di &si dovrebbe utilizzare &amp;o utilizzare un CDATAblocco.


1
Non è corretto Il punto di utilizzoLegacyDatetimeCode = false non deve specificare serverTimezone, quindi il client corregge le differenze di fuso orario.
antgar9,

Questo ha funzionato per me collegandomi a MySQL 5.7 con phpStorm 2019.1.4.
moult86

29

Questo è un bug in mysql-connettore-java dalla versione 5.1.33 alla 5.1.37. L'ho segnalato qui: http://bugs.mysql.com/bug.php?id=79343

Modificato: questo è stato corretto da mysql-connettore-java 5.1.39

È stato un refuso nella classe TimeUtil nel metodo loadTimeZoneMappings che genera un NPE che individua il file /com/mysql/jdbc/TimeZoneMapping.properties. Se guardi il codice, il file dovrebbe trovarsi nel programma di caricamento classi TimeUtil, non TimeZone:

TimeUtil.class.getResourceAsStream(TIME_ZONE_MAPPINGS_RESOURCE);

Il parametro useLegacyDatetimeCode consente di correggere automaticamente la differenza tra fusi orari client e server quando si utilizzano le date. Quindi ti aiuta a non dover specificare i fusi orari in ciascuna parte. Sebbene l'utilizzo del parametro serverTimeZone sia una soluzione alternativa e nel frattempo la patch viene rilasciata, puoi provare a correggere meglio il codice da solo come ho fatto io.

  • Se si tratta di un'applicazione autonoma, puoi semplicemente provare ad aggiungere una classe com / mysql / jdbc / TimeUtil corretta al tuo codice e fare attenzione con l'ordine di caricamento del vaso. Questo può aiutarti: https://owenou.com/2010/07/20/patching-with-class-shadowing-and-maven.html

  • Se si tratta di un'applicazione web, la soluzione più semplice è creare il proprio mysql-connettore-java-5.1.37-patched.jar, sostituendo il .class direttamente nel vaso originale.


Dolce grazie per aver segnalato questo. Sono contento che qualcuno sia stato in grado di individuare il bug. Sai quando verrà rilasciata la correzione?
bluecollarcoder,

La soluzione che stai suggerendo è eccezionale, ma penso che modificare la fonte del driver e gestire la dipendenza Maven sia probabilmente troppo fastidioso per la maggior parte delle persone.
bluecollarcoder,

4
@Gili Questo non è stato risolto dalla versione 6.0.6
Imme22009 del

6
Il bug è presente in 8.0.11
John Little

3
@JohnLittle Ho anche questo problema in 8.0.15, ma non è più causato dal bug. I fusi orari sono caricati correttamente, ma CET e CEST (questi fusi orari mi causano problemi) non sono inclusi né in TimeZone.getAvailableIDs()né in TimeZoneMapping.propertiesquindi questa soluzione non aiuta qui. La soluzione sarebbe probabilmente impostata comeserverTimezone=Europe/Berlin
JPT

29

Ho risolto inserendo la stringa di connessione sotto l'URL

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

1
Non è corretto Il punto di utilizzoLegacyDatetimeCode = false non deve specificare serverTimezone, quindi il client corregge le differenze di fuso orario.
antgar9

25

Ha funzionato per me semplicemente aggiungendo serverTimeZone = UTC su application.properties.
spring.datasource.url=jdbc:mysql://localhost/db?serverTimezone=UTC


22
  1. Ho aggiunto il file di configurazione mysql nella sezione [mysqld]

    default_time_zone='+03:00'
  2. E riavvia il server mysql:

    sudo service mysql restart

Dove +03: 00 il mio fuso orario UTC.

Percorso del file di configurazione sul mio sistema operativo Ubuntu 16.04:

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

ATTENZIONE: SE LA TUA FUSO ORARIO HA L'ESTATE E L'INVERNO. È NECESSARIO MODIFICARE UTC IN CONFIG SE SE CAMBIA TEMPO. DUE VOLTE IN ANNO (USUALMENTE) O SET CRONTAB CON SUDO.

La mia connessione jdbc url:

"jdbc:mysql://localhost/java"

1
Dover riavviare Mysql è fondamentalmente un avviatore in quasi tutti i casi d'uso di produzione. Diventa ancora più un problema quando sono coinvolte le repliche.
bluecollarcoder,

@bluecollarcoder Richiede l'aggiunta solo nella sezione [mysqld]. Oppure aggiungi la sezione [mysqld] se non ce l'ha. Esempio la mia configurazione pastebin.com/j4F7t2KS
Fortran,

1
Ho aggiornato il mio server Linux / etc / localtime da / usr / share / zoneinfo / US / Pacific a / usr / share / zoneinfo / America / Los_Angeles, quindi ho riavviato il servizio mysql e questo ha risolto il problema per me.
vinnyjames,

Nel mio caso per la sintassi fornita, si è verificato un errore al riavvio e la sintassi corretta era: default-time-zone='+03:00'invece, come da questa risposta . Proviene anche da DBeaver.
wscourge

non è appropriato se devi dire a tutti gli sviluppatori della tua azienda di modificare la loro configurazione MySQL :)
pheromix

16

Ho lo stesso problema e l'ho risolto aggiungendo solo "? ServerTimezone = UTC" alla mia connessione di stringa.

#

sinossi il mio problema:

java.sql.SQLException: il valore del fuso orario del server 'CEST' non è riconosciuto o rappresenta più di un fuso orario. È necessario configurare il server o il driver JDBC (tramite la proprietà di configurazione serverTimezone) per utilizzare un valore di fuso orario più specifico se si desidera utilizzare il supporto del fuso orario.

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 

14

Il programma sopra genererà quell'errore di fuso orario.

Dopo il nome del database è necessario aggiungere questo: ?useTimezone=true&serverTimezone=UTC. Una volta che hai fatto il tuo codice funzionerà bene.

Buona fortuna :)



13

Tutto ciò di cui abbiamo bisogno per risolvere il problema con serverTimezone:

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

È successo anche a me con l'ultima versione 5.4.15. Ma risolto con questo: l'aggiunta di "? ServerTimezone =" + TimeZone.getDefault (). GetID () "proprio accanto al tuo database, risolve i problemi.
Tes

10

Puoi utilizzare il connettore MySQL nella dipendenza Maven,

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

Quindi è necessario impostare i parametri giusti nel application.propertiesfile,

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

Sto usando mysql-connettore-java-8.0.13 e ho avuto lo stesso problema. Ho creato il mio database nella console della riga di comando e risolto questo problema utilizzando la soluzione di @Dimitry Rud sulla riga di comando:

SET GLOBAL time_zone = '-6:00';

Non ho avuto bisogno di riavviare nulla, impostare l'ora ed eseguire immediatamente il mio codice in Eclipse, collegato senza problemi.

Il bug dovrebbe essere corretto in una versione precedente, ma penso di aver ricevuto questo errore perché dopo aver creato il database nella console, non l'ho impostato. Non sto usando workbench né un'altra app per gestire questo piuttosto che la console.


6

Da mysql workbench esegui le seguenti istruzioni sql:

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

con le seguenti istruzioni sql verificare se sono stati impostati i valori:

SELEZIONA @@ global.time_zone, @@ session.time_zone;


2
Questo ha funzionato per me quando l'errore in questione è apparso durante il tentativo di stabilire una connessione da IntelliJ IDEA.
Faheem Hassan Zunjani,

6

Questo ha funzionato per me.

su DBeaver 6.0: andare su Impostazioni connessione> Proprietà driver> Fuso orario server> Imposta UTC.

Inoltre, in Spring Boot Config, è stato necessario impostare la proprietà sotto.

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


5

Apparentemente, per far funzionare la versione 5.1.33 del driver MySQL JDBC con il fuso orario UTC, è necessario specificare esplicitamente serverTimezone nella stringa di connessione.

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

3

Avevo anche lo stesso identico problema in LibreOffice Base. Quindi ho appena specificato un "fuso orario di ora legale" nella stringa di connessione.
** inserisci qui la descrizione dell'immagine **

Ho provato senza "& serverTimezone = MST" ma anche questo non è riuscito.

Ho anche provato "& serverTimezone = MDT" e questo non è riuscito, quindi per qualche ragione non mi piace l'ora legale!


3

Ho avuto lo stesso problema quando provo a lavorare con il progetto di avvio a molla su Windows.

L'URL dell'origine dati dovrebbe essere:

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


3

Esegui sotto query al database mysql per risolvere l'errore

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

Ho ricevuto un errore simile al tuo ma il mio Il valore del fuso orario del server è 'Afr. centrale Ouest 'quindi ho fatto questi passaggi:

MyError (su IntelliJ IDEA Community Edition):

    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....

Ho riscontrato questo problema quando ho aggiornato il mio server mysql a SQL Server 8.0 (MYSQL80).

La soluzione più semplice a questo problema è semplicemente scrivere il comando seguente nel tuo MYSQL Workbench -

  SET GLOBAL time_zone = '+1:00'

Il valore dopo il fuso orario sarà uguale alla differenza GMT +/- nel tuo fuso orario. L'esempio sopra è per il Nord Africa (GMT + 1: 00) / o per l'India (GMT + 5: 30). Risolverà il problema.

Inserisci il codice seguente nel tuo Mysql Workbench ed esegui query

[link sorgente per domanda / problema]

[link sorgente per risposta]

[Soluzione ScreenShot]


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

Questa è in realtà la soluzione a questo problema, ma non limitarti a copiarlo e incollarlo nel tuo programma. Se hai appena letto la riga troverai 'resultout', questo è il nome del mio database e devi scrivere il tuo.

Esistono tre componenti di stringa, il primo è url, il secondo è username e il terzo è password. Nel paragrafo precedente abbiamo eliminato, url. Il secondo e il terzo componente String come detto nome utente e password devono essere modificati di conseguenza.

Grazie


1

Ho risolto questo problema senza alcuna modifica del codice. basta andare all'impostazione dell'ora di sistema e impostare il fuso orario. Nel mio caso il fuso orario predefinito era UTC che ho cambiato nel mio fuso orario locale. Dopo aver riavviato tutti i servizi, tutto ha funzionato per me.


1

Sono in ritardo, ma se stai riscontrando problemi con il seguente errore e utilizzando l'origine dati (javax.sql.DataSource):

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

Impostare la seguente riga per eliminare l'errore:

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

1

Nel mio caso, si trattava di un ambiente di test e ho dovuto fare in modo che un'applicazione esistente funzionasse senza modifiche alla configurazione e, se possibile, senza modifiche alla configurazione di MySQL. Sono stato in grado di risolvere il problema seguendo il suggerimento di @vinnyjames e cambiando il fuso orario del server in UTC :

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

Farlo mi è bastato per risolvere il problema.


1

Ho aggiunto la seguente riga al mio /etc/mysql/my.cnffile:

default_time_zone='+00:00'

Riavviato il server MySQL:

systemctl restart mysql

E funziona come un fascino.


1

Non vi è alcun impatto sull'impostazione dell'ora del server come UTC (ad esempio jdbc:mysql://localhost:3306/myschema?serverTimezone=UTC, anche se i server dell'applicazione / database non si trovano in questo fuso orario. L'importante è che la stringa di connessione dell'applicazione + il database siano sincronizzati con lo stesso fuso orario.

In altre parole, la semplice impostazione serverTimezone=UTCcon un fuso orario diverso sul server di database sposta tutte le date estratte dal database


0

Accetto con la risposta di @bluecollarcoder, ma è meglio usare TimeZone.getDefault().getID();alla fine della stringa di connessione:

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

In questo caso il Timezoneparametro si aggiorna automaticamente in base al fuso orario della macchina locale.


Non è corretto Il punto di utilizzoLegacyDatetimeCode = false non deve specificare serverTimezone, quindi il client corregge le differenze di fuso orario.
antgar9

0

Basta modificare la stringa di connessione con il seguente codice nel file application.properties.


spring.datasource.url=jdbc:mysql://localhost:3301/Db?
   useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=
   false&serverTimezone=UTC
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.