MySQL Connector/J 5.1 系では useLegacyDatetimeCode=false にしよう
JDBC で MySQL に接続するときに使用する MySQL Connector/J (mysql:mysql-connector-java) の話。 サーバー・クライアントのタイムゾーン設定が違っている場合にどう対応するのがいいか。
結論
- MySQL Connector/J 6 (まだ開発版だけど) 以降は自動でやってくれるので気にする必要はない。
- MySQL Connector/J 5.1 では URL に
useLegacyDatetimeCode=false
を入れて、時刻周りの新しい処理が動くようにしろ。- 新しい処理では、タイムゾーンの変換を一貫性をもってやってくれるようになる。
- 『Use code for DATE/TIME/DATETIME/TIMESTAMP handling in result sets and statements that consistently handles time zone conversions from client to server and back again』
- 参考 : 5.1 Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J
- 5.1 系ではデフォルトでは互換のために新しい処理は動かないようになっているので、明示的に新しい処理を使うように URL で指定する必要がある。
- バージョン 5.1.6 で導入された機能なので、それより古いものでは使えない。
問題
そもそもどういう問題に遭遇したのか。
- Java のアプリケーションサーバーのタイムゾーンが JST。
- MySQL サーバーのタイムゾーンが UTC。
- Java アプリケーションから MySQL サーバーには MySQL Connector/J 5.1 系で接続。
- タイムゾーン周りのオプションは何も指定せず。
- SQL 文の
NOW()
関数やDEFAULT CURRENT_TIMESTAMP
で設定された時刻を Java アプリケーション側で取得すると、現在時刻から 9 時間前の時刻が返ってきた。 - → MySQL Connector/J がサーバー・クライアント間のタイムゾーン差を扱ってくれてない。
MySQL Connector/J とタイムゾーン
- もともとは
useTimezone
プロパティやserverTimezone
プロパティを使って対応する必要があった。 - MySQL Connector/J 5.1.6 で時刻周りの処理が書き直されて、
useLegacyDatetimeCode=false
することでタイムゾーン変換などを自動で扱ってくれるようになった。 - MySQL Connector/J 6 では
useLegacyDatetimeCode
プロパティを含め、古いタイムゾーン周りのプロパティは全部削除される。
おわり
タイムゾーンはライブラリ側がちゃんと面倒見てくれるだろう、と思って気にしなかったら、環境を変えて Java アプリケーションと MySQL サーバーのタイムゾーン設定がずれたときにいきなり想定しない動作になったりするので気を付けましょう。