Spring WebFlux
/R2DBC
/jOOQ
/PostgreSQL
/Kotlin Coroutines
環境で、不意にselect
クエリがハングする状況が何度か有りました。
関連する内容が多すぎて原因は解析し切れていませんが、そのような状況に対して見出した3つの対処法をまとめます。
何かより良い対処法をご存じの方いらっしゃいましたらコメント頂けると嬉しいです。
1. Flow内から別クエリを呼び出さないようにする
1発目から無条件でハングする場合、まずこれが疑われます。
特にトランザクションが有効になっているような場合、「前のクエリが終わってなくてコネクションを掴めない ⇔ クエリ結果の消費が終わらなくてコネクションを放せない」というように、デッドロックしてしまうことが有ります。
Flow
はtoList
するなりして消費し切ってから次のクエリを発行しましょう。
また、これが起きるということは基本的に1+Nクエリ状態となっているはずなので、そこを見直すのも手です。
2. プリペアドステートメント無し/jOOQ
を介さずクエリを発行する
数回実行した後にハングする場合、この対処が効く可能性が有ります。
この方法は、プリペアドステートメントを使わないようにする = クエリに全て埋め込む必要がある = クエリログ等に情報が出てしまう点に注意が必要です。
もしかすると、後述する3の方法の方が良いかもしれません。
実際にこれを実装した例は以下にまとめてあります。
wrongwrong163377.hatenablog.com
3. クエリにランダムな文字列を埋め込んで発行する
これも2と同様の状況に対し効果が有るようでした。
ただし、2の方法よりは検証し切れていません。
例えばLocalTime.nano() >= 0
のようにランダム性のある条件を生で埋め込む(プリペアドステートメント利用にしない)ことで、2と同様の効果が有るようでした。
この方法であればプリペアドステートメントも利用できるようでした。
その他
クエリが本当に遅いケースも有るため、まずはどんなクエリが発行されているか確認すべきです。
自分が経験したケースでは、「実行計画がおかしくなっていたせいでDBeaver
を使ったアクセス時のみ高速になる」というようなことも有ったため、接続・取得の条件を揃えてあげることも重要でした。