postgresql エラー: current transaction is aborted commands ignored until end of transaction block


発生した状況

Transaction中に行ロックを実装していた時に発生したエラーです。
以下の行取得エラーを期待していました。

pq: could not obtain lock on row in relation "table_xxxx"

↑は「行ロックされているので、取得できないですよ〜」ということ。

pq: current transaction is aborted, commands ignored until end of transaction block

しかし、意図に反して↑のメッセージが発生しました。つまり「現在のトランザクションを中止します。コマンドはトランザクションブロックが終了するまで無視されます」というエラーが発生しはじめました

処理の全体図

もう少し詳しく

実は、行ロック取得エラーをフックして、同トランザクション内で別処理を行おうとしていた時に発生しています。

エラーが発生する処理の全体図

原則として、postgresのトランザクションでエラー発生後、別のクエリを実行するためには、ロールバックを使用してトランザクションをクリアする必要があるということでした。トランザクションでエラーを放置してしまうと全ての処理は実行されないということです(今回はこれに相当してます)。
エラーフックはそもそも同一トランザクションではできないということですね。

ロールバックとは

ROLLBACKは、現在のトランザクションをロールバックし、トランザクションによって行われたすべての更新を破棄すること。(Description: ROLLBACK)

解決方法

トランザクション内でエラーをフックして別処理などを行えないので、必ずエラー発生後はロールバックしてトランザクションをクリーンな状態にすれば発生しなくなります。
ドキュメントにもトランザクション中のエラーについては言及されています。

トランザクションは全てのデータベースシステムで基礎となる概念です。トランザクションの基本的要点は複数の手順を単一の「全てかなしか」の操作にまとめ上げることです。手順の進行途中の状態は他の動いているトランザクションからは見えません。 そして、何らかのエラーが起こるとトランザクションは完結しません。ですからデータベースはエラーの原因となった手順によってまったく影響されることはありません。