LoginSignup
3
2

More than 5 years have passed since last update.

PostgreSQLのJDBCドライバをアップデートしたら少しハマった話

Posted at

背景

  • Spring Boot 1.5 アプリケーション
  • PostgreSQL 9.6
  • DBアクセスはJDBC

PostgreSQLのJDBCドライバは、batchUpdate()で複数行をINSERTしてもレコード数分のINSERT文を作成します。
これでは遅いので高速化のためにBULK INSERTしたい。

ドライバ9.4.1209からreWriteBatchedInsertsというオプションが追加されており、これを設定することでBULK INSERTになるのですが、INSERT ON CONFLICT使用時に不正なSQLを生成してしまう不具合があり、これが解消されているのが42.2.2
ところが、Spring Boot 1.5系で導入されるのは9.4.1212。。。

ということで、ドライバのバージョンを上げることにしました。

バージョンアップしてみた

pom.xmlに以下を追加し、最新の42.2.4を導入します。

pom.xml
  <properties>
    ...
    <postgresql.version>42.2.4</postgresql.version>
    ...
  </properties>

これだけです。簡単ですね。

ところが。

ビルドするとテストがエラーを吐きました。

Expected :2015-12-15 23:30:59.999999
Actual   :2015-12-15 23:31:00.0

ドライバのバージョンを戻すとエラーは消えるので、バージョンアップの影響であることは確実です。

調査

テストが落ちる原因はタイムスタンプが繰り上がってしまっているためです。
Read/Writeどちらで問題が発生しているのか確認するために、このドライバを経由せずにDBのデータを覗いてみたところ、繰り上がったレコードが登録されているので、どうやら書き込む際に既に不正なデータになっているようです。

何故だ。

あれこれググってみると、あるIssueを見つけました。
これによると、バージョン42.1.1以降で発生する問題で、42.2.3では修正されている。
あれ?じゃあ問題は修正されている・・・?

解決

このIssueがキッカケで、バージョン42.1.1以降ではjava.sql.Timestampのnano秒を、micro秒までの精度であるDBのTimestampに変換する際に、四捨五入していることと、これより前のバージョンではnano秒を無視していたことが分かりました。

で、テスト用のConfigurationを確認してみると・・・。

public Clock clock() {
    return Clock.fixed(ZonedDateTime.of(2015, 12, 15, 23, 30, 59, 999999999, ZoneId.systemDefault()).toInstant(), ZoneId.systemDefault());
}

nano秒まで埋めてた!

ということで、999999999999999000にして解決しました。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2