[java] MySQL JDBC 드라이버 5.1.33-시간대 문제

일부 배경 :

Tomcat 7에서 Java 1.6 webapp을 실행하고 있습니다. 데이터베이스는 MySQL 5.5입니다. 이전에는 Mysql JDBC 드라이버 5.1.23을 사용하여 DB에 연결했습니다. 모든 것이 효과가있었습니다. 최근에 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.

왜 이런 일이 발생합니까?



답변

분명히 UTC 시간대와 작동하도록 MySQL JDBC 드라이버 버전 5.1.33을 얻으려면 serverTimezone연결 문자열에 명시 적으로 지정해야 합니다.

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


답변

MySQL을 구성하여이 문제를 해결했습니다.

SET GLOBAL time_zone = '+3:00';


답변

이 주제에 대한 여러 게시물을 읽은 후 다른 구성을 테스트 하고이 mysql 버그 스레드의 통찰력을 바탕으로 이해했습니다.

  • 서버 시간대는 특히 데이터베이스에 저장된 날짜를 애플리케이션 서버의 시간대로 변환하는 데 중요합니다. 다른 의미가 있지만 이것은 가장 눈에 띄는 것입니다
  • GMT x UTC 시간대 시스템. GMT는 19 세기 후반에 고안되었으며 표준 시간과 여름 시간 사이에서 전환 될 수 있습니다. 이 속성은 데이터베이스 서버가 서머 타임으로 이동하고 응용 프로그램에서이를 알지 못하는 상황으로 이어질 수 있습니다 (아마도 다른 합병증이 있지만 더 연구하지는 않았습니다). UTC는 시간에 따라 변하지 않습니다 (항상 0 ° 경도에서 평균 태양 시간의 약 1 초 이내).
  • serverTimeZone 정의는 mysql jdbc 커넥터 버전 5.1 이상에서 도입되었습니다. 버전 8까지는를 사용하여 무시할 수 있으며 useLegacyDatetimeCode=true, 이로 useJDBCCompliantTimezoneShift=true인해 응용 프로그램은 모든 연결에서 데이터베이스 시간대를 가져옵니다. 이 모드에서 ‘British Summer Time’과 같은 GMT 시간대는 내부 java / JDBC 형식으로 변환됩니다. .properties 인으로 정의 할 수 있습니다 새로운 시간대 등의 파일 이 하나
  • jdbc 드라이버 버전 8부터는 자동 시간 일치 ( useJDBCCompliantTimezoneShift) 및 레거시 시간 형식 ( useLegacyDatetimeCode)이 제거되었습니다 ( mysql jdbc 커넥터 changelog 참조 ). 따라서이 두 매개 변수를 설정해도 완전히 무시되므로 아무런 영향을 미치지 않습니다 (새로운 기본값은 useLegacyDateTimeCode=false).
  • 이러한 방식으로 시간대 (응용 프로그램 / 데이터베이스 서버)가 ‘UTC + xx’또는 ‘GMT + xx’형식이 아닌 경우 설정 serverTimezone필수 가되었습니다.
  • jdbc:mysql://localhost:3306/myschema?serverTimezone=UTC응용 프로그램 / 데이터베이스 서버가이 시간대에없는 경우에도 서버 시간을 UTC로 설정해도 아무런 영향을 미치지 않습니다. 응용 프로그램 연결 문자열 + 데이터베이스가 동일한 시간대와 동기화되는 것이 중요합니다. , 단순히 serverTimezone을 설정하는 UTC는 데이터베이스에서 추출 된 어떤 날짜를 이동합니다 데이터베이스 서버에서 다른 시간대로 =
  • MySQL 기본 시간대는 줄을 추가하여 my.ini 또는 my.cnf 파일 (각각 Windows / Linux)을 사용하여 UTC + 0으로 설정할 수 있습니다 default-time-zone='+00:00'( 이 StackOverflow 게시물의 세부 사항 참조 ).
  • AWS (amazon 웹 서비스)에 구성된 데이터베이스에는 UTC + 0 기본 시간이 자동으로 할당됩니다 ( AWS 도움말 페이지 참조 ).

답변

Maven을 사용하는 경우 다음과 같이 다른 MySQL 커넥터 버전을 설정할 수 있습니다 (같은 오류가 있으므로 6.0.2에서 5.1.39로 변경되었습니다) 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>

Maven은 pom.xml파일 을 저장 한 후 프로젝트를 자동으로 다시 빌드합니다 .


답변

연결 문자열은 다음과 같이 설정해야합니다.

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

당신이에 연결을 정의 할 경우 xml파일을 (예 : persistence.xml, standalone-full.xml, 등), 대신 &사용해야 &amp;하거나 사용 CDATA블록을.


답변

이것은 mysql-connector-java 버전 5.1.33에서 5.1.37까지의 버그입니다. 나는 그것을 여기에보고했다 : http://bugs.mysql.com/bug.php?id=79343

편집 : 이것은 mysql-connector-java 5.1.39에서 수정되었습니다.

loadTimeZoneMappings 메소드에서 TimeUtil 클래스의 오타로 /com/mysql/jdbc/TimeZoneMapping.properties 파일을 찾는 NPE를 발생시킵니다. 코드를 보면 파일이 TimeZone이 아니라 TimeUtil 클래스 로더 내에 있어야합니다.

TimeUtil.class.getResourceAsStream(TIME_ZONE_MAPPINGS_RESOURCE);

useLegacyDatetimeCode 매개 변수를 사용하면 날짜를 사용할 때 클라이언트와 서버 시간대의 차이를 자동으로 수정할 수 있습니다. 따라서 각 부분에 시간대를 지정할 필요가 없습니다. 사용 Althought serverTimeZone의 매개 변수를하는 것은 문제를 해결하고, 그 사이에 패치가 발표되어, 당신은 내가 그랬던 것처럼 스스로 코드를 수정 더 시도 할 수 있습니다.

  • 독립형 응용 프로그램 인 경우 수정 된 com / mysql / jdbc / TimeUtil 클래스를 코드에 추가하고 jar 로딩 순서에주의하십시오. 도움이 될 수 있습니다 :
    https://owenou.com/2010/07/20/patching-with-class-shadowing-and-maven.html

  • 웹 응용 프로그램 인 경우 더 쉬운 해결책은 .class를 원래 jar로 직접 대체하여 자신의 mysql-connector-java-5.1.37-patched.jar을 만드는 것입니다.


답변

URL에 연결 문자열을 넣는 것을 해결했습니다.

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