[Postgres] current transaction is aborted, commands ignored until end of transaction block

January 11, 2018

postgresのクライアントでSQLを実行した際、突然クエリを正しく入力したにもかかわらず、実行できなくなったことがある。

結構ハマったので、このエラーについてまとめておく。

原因

PostgresTransaction内に一度エラーが発生すると、明示的にそのTransactionabortしなければならないのだ。

因みに、SQL Server等の他のRDBMSだと、エラーが出てきても、その場でクエリを見直しして、処理を続けるんだね。

[例]

begin;
selet
* from foo; -- わざとseletにした

このクエリを実行すると、「ERROR: syntax error at or near ‘selet’“」が出るはず。

これで気づいてselect * from foo;の正しいクエリに修正して、再度実行すると、冒頭のエラーが出ることがわかる。

対策

rollback;

を一度実行してから、最初からトランザクションを実行しなければならない。

なぜPostgresはそうなったのか?

Postgresはユーザで終了したTransactionとシステムの都合(例外等)で終了したTransactionは区別しているようだ。 https://github.com/postgres/postgres/blob/master/src/backend/access/transam/README を参照すると、

  1. システムの都合でTransactionが終了した場合:AbortCurrentTransaction アプリケーション状態はTBLOCK_ABORT
  1. ユーザでTransactionを終了した場合:UserAbortTransactionBlock アプリケーション状態はTBLOCK_ABORT_END

ケース1でも自動にTransactionを終了させれば良いでしょうかって思うよね。

実はそれに応じるonerrorrollbackオプションがあるが、やっぱり長いTransaction内にエラーが発生したら、最初から実施しないといけない点は不便が感じるよね〜

onerrorrollbackについての詳細説明も是非ご参照ください。 https://www.endpoint.com/blog/2015/02/24/postgres-onerrorrollback-explained

Initializing...