PSQLException:現在のトランザクションは中止され、トランザクションブロックが終了するまでコマンドは無視されます


151

JBoss 7.1.1 Finalのserver.logファイルに次の(切り捨てられた)スタックトレースが表示されます。

Caused by: org.postgresql.util.PSQLException: 
ERROR: current transaction is aborted, commands ignored until end of 
transaction block

at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:374)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:302)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_23]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_23]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_23]
at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_23]
at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$StatementHandler.invoke(AbstractJdbc23PooledConnection.java:455)
at $Proxy49.executeUpdate(Unknown Source)   at org.jboss.jca.adapters.jdbc.WrappedStatement.executeUpdate(WrappedStatement.java:371)
at org.infinispan.loaders.jdbc.TableManipulation.executeUpdateSql(TableManipulation.java:154) [infinispan-cachestore-jdbc-5.1.2.FINAL.jar:5.1.2.FINAL]
... 154 more

Postgresログファイルを調べると、次のステートメントがわかります。

STATEMENT:  SELECT count(*) FROM ISPN_MIXED_BINARY_TABLE_configCache
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  CREATE TABLE ISPN_MIXED_BINARY_TABLE_configCache(ID_COLUMN VARCHAR(255) NOT NULL, DATA_COLUMN BYTEA, TIMESTAMP_COLUMN BIGINT, PRIMARY KEY (ID_COLUMN))
ERROR:  relation "ispn_mixed_binary_table_configcache" does not exist at character 22

私はJBoss 7.1.1 Finalに同梱されているInfinispanを使用しています。これは5.1.2.Finalです。

これが起こっていると私が思うことです:

  • InfinispanはSELECT count(*)...ステートメントを実行して、にレコードがあるかどうかを確認しISPN_MIXED_BINARY_TABLE_configCacheます。
  • Postgresは、何らかの理由で、この声明を好まない。
  • Infinispanはこれを無視し、CREATE TABLEステートメントを前に進めます。
  • Postgres barfsは、Infinispanがロールバックに失敗したのと同じトランザクションであるとまだ認識しているため、このトランザクションは最初のSELECT count(*)...ステートメントから実行されます。

このエラーは何を意味し、それを回避する方法はありますか?


上記のPSQLException: current transaction is aborted...25P02)を検索する私のようにここに来た場合でも、JPAまたはHibernate。最後に、私たちの(!ナイス)によるものであったLogbackので供給用法toString():エラーの原因となったと(私ではなくaccidentially気付かない)きれいに飲み込まれた-overloaded DAOオブジェクトをlog.info( "bla bla: {}", obj )生成しますbla bla: [FAILED toString()]log.info( "bla bla: {}", String.valueOf( obj )これをnullセーフに変更しましたが、飲み込まないため、トランザクションを開いたままにして、関連のないクエリで失敗しました。
Andreas Dietrich

同じタイプのエラーが発生しました。SQLの前に接続を解放する必要がありました。私のコードはconnection.commit()
mdでした。ariful ahsan

回答:


203

テーブルで挿入を行うJavaとpostgresqlを使用してこのエラーが発生しました。このエラーを再現する方法を説明します。

org.postgresql.util.PSQLException: ERROR: 
current transaction is aborted, commands ignored until end of transaction block

概要:

このエラーが発生する理由は、トランザクションを入力し、SQLクエリの1つが失敗し、その失敗を取り除いて無視したためです。しかし、それだけでは十分ではなく、同じ接続を使用し、同じトランザクションを使用して別のクエリを実行しました。追加の作業を行うために壊れたトランザクションを使用しているため、正しく形成された2番目のクエリで例外がスローされます。デフォルトでは、Postgresqlはこれを阻止します。

私が使用しています: PostgreSQL 9.1.6 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2), 64-bit".

私のpostgresqlドライバは: postgresql-9.2-1000.jdbc4.jar

Javaバージョンの使用: Java 1.7

以下は、例外を説明するためのテーブル作成ステートメントです。

CREATE TABLE moobar
(
    myval   INT
);

Javaプログラムでエラーが発生する:

public void postgresql_insert()
{
    try  
    {
        connection.setAutoCommit(false);  //start of transaction.

        Statement statement = connection.createStatement();

        System.out.println("start doing statement.execute");

        statement.execute(
                "insert into moobar values(" +
                "'this sql statement fails, and it " +
                "is gobbled up by the catch, okfine'); ");

        //The above line throws an exception because we try to cram
        //A string into an Int.  I Expect this, what happens is we gobble 
        //the Exception and ignore it like nothing is wrong.
        //But remember, we are in a TRANSACTION!  so keep reading.

        System.out.println("statement.execute done");

        statement.close();

    }
    catch (SQLException sqle)
    {
        System.out.println("keep on truckin, keep using " +
                "the last connection because what could go wrong?");
    }

    try{
        Statement statement = connection.createStatement();

        statement.executeQuery("select * from moobar");

        //This SQL is correctly formed, yet it throws the 
        //'transaction is aborted' SQL Exception, why?  Because:
        //A.  you were in a transaction.
        //B.  You ran a sql statement that failed.
        //C.  You didn't do a rollback or commit on the affected connection.

    }
    catch (SQLException sqle)
    {
        sqle.printStackTrace();
    }   

}

上記のコードは私のためにこの出力を生成します:

start doing statement.execute

keep on truckin, keep using the last connection because what could go wrong?

org.postgresql.util.PSQLException: 
  ERROR: current transaction is aborted, commands ignored until 
  end of transaction block

回避策:

いくつかのオプションがあります。

  1. 最も簡単な解決策:トランザクションに参加しないでください。をに設定connection.setAutoCommit(false);connection.setAutoCommit(true);ます。失敗したSQLは、失敗したSQLステートメントとして無視されるため、機能します。必要に応じてsqlステートメントを失敗させてもかまいません。postgresqlが停止することはありません。

  2. トランザクション内にとどまりますが、最初のSQLが失敗したことを検出したら、トランザクションをロールバック/再起動するか、コミット/再起動します。その後、そのデータベース接続で必要なだけSQLクエリを失敗させ続けることができます。

  3. SQLステートメントが失敗したときにスローされる例外をキャッチして無視しないでください。その後、プログラムは不正なクエリで停止します。

  4. 代わりにOracleを取得します。トランザクション内の接続でクエリが失敗し、その接続を引き続き使用しても、Oracleは例外をスローしません。

この方法で事を行うというpostgresqlの決定を擁護して...オラクル途中であなたを柔らかくして、あなたが馬鹿なことをしてそれを見落とすようにしていました。


10
Lol @オプション4 ...私はOracleでかなりの開発を行っており、最近Postgresを使い始めました... Postgresがこれを行うのは本当にうっとうしいことです。 OracleからPostgresに移植しています。最初のようにOracleのように動作させるが、自動コミットなしのオプションがないのはなぜですか?
ADTC 2013

2
いくつかの試行の結果、オプション2がOracleの動作に最も近いことがわかりました。複数の更新を発行する必要があり、1つの失敗で後続の更新が停止しない場合は、がキャッチさrollback()れたConnectionときにを呼び出すだけSQLExceptionです。[ とにかくこれは、ユーザーにすべてを明示的にすることを強制するというPostgreSQLの哲学と一致していることに気付きましたが、Oracleは暗黙のうちに多くのことを処理する哲学です。]
ADTC

2
オプション2には不可能なブランチが含まれていますor commit/restart the transaction。私が見ることができるように、例外の後にコミットする方法はありません。私がコミットしようとするとrollback
-PostgreSQLが

1
@turbanoffで発生した問題を確認できます。これはで直接再現することもできpsqlます。(1)トランザクションを開始する、(2)有効なステートメントを発行する、(3)無効なステートメントを発行する、(4)commit-> psqlはコミットするのではなくロールバックする
Alphaaa

1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl このトピックに関する興味深いディスカッション。この問題が制約違反によって引き起こされた場合、PostgreSQL開発者は事前に競合をチェックするか(更新/挿入前のクエリ)、またはを使用savepointsして更新/挿入前のポイントにロールバックすることをお勧めします。サンプルコードについては、stackoverflow.com / a / 28640557/14731をご覧ください。
Gili

27

を引き起こしたステートメントのの出力を確認してくださいcurrent transaction is aborted。これは通常、コードが無視した例外がデータベースからスローされ、次のクエリがデータを返すことを期待していることを意味します。

これで、問題がないことを考慮したアプリケーションとデータベースの状態が一致しなくなり、トランザクションを最初からロールバックして再開する必要があります。

このような場合は、すべての例外とロールバックトランザクションをキャッチする必要があります。

これは同様の問題です。


これは素晴らしいことですが、この場合は、サードパーティのライブラリであるInfinispanがPostgresと通信していて、私のコードではありません。
ジミディ

まあ、状況は同じです—トランザクションをロールバックする必要があります。使用しているライブラリの新しいバージョンがあるかどうかを確認するか、バグトラッカーで問題を報告してください。SQL問題の原因が正確にわかる場合は、PostgreSQLの拡張性を使用して問題を解決するためのフィールドがあります。
vyegorov

あなたは私の疑いを確認したようです-今からInfinispan 5.1.2のソースを見ていきます。
ジミディ

公平を期すために、TableManipulationクラスでは、select count(*)を実行しようとする試みの周りにtry-catchがあります。おそらくPostgresドライバが予期された例外の1つをスローしていません。詳細については、デバッガをJBossに接続して確認します。
ジミディ

問題のInfinispanコードがこのバグで提案されました:issues.jboss.org/browse/… ライブJBoss 7.1.1インスタンスで実行されているデバッガーにデバッガーを接続し、Postgresが適切な場所で例外をスローしています。おそらく、JdbcUtil.safeClose()ステートメントがその仕事をしていません。私はインフィニスパンでそれを上げるつもりです。
ジミディ

13

最善の解決策はjava.sql.Savepointを使用することだと思います。

SQLExceptionをスローできるクエリを実行する前に、メソッドConnection.setSavepoint()を使用します。例外がスローされる場合は、このセーブポイントにのみロールバックし、すべてのトランザクションをロールバックしません。

コード例:

Connection conn = null;
Savepoint savepoint = null;
try {
    conn = getConnection();
    savepoint = conn.setSavepoint();
    //execute some query
} catch(SQLException e) {
    if(conn != null && savepoint != null) {
        conn.rollback(savepoint);
    }
} finally {
   if(conn != null) {
      try {
          conn.close();
      } catch(SQLException e) {}

   }
}

私は誤ってなんとかして反対票を投じましたが、気づいただけです。意図的なものではありませんでした。回答を編集しない限り、元に戻すことはできません。
cerberos

セーブポイント方式は実際のソリューションです。PHP、Doctrine2、Postgres(9.5)の環境でも動作します。ありがとう
helvete

6

この動作に関連して、postgresql JDBCドライバーでいくつかの作業が行われています。https//github.com/pgjdbc/pgjdbc/pull/477を
参照してください

設定することで可能になりました

autosave = always
接続(https://jdbc.postgresql.org/documentation/head/connect.htmlを参照)で、「現在のトランザクションが中止されました」シンドロマを回避します。
ステートメント実行の前後でセーブポイントを処理することによるオーバーヘッドは非常に低く保たれます(詳細は上記のリンクを参照)。


5

Ruby on Rails PGでは、移行を作成し、DBを移行しましたが、開発サーバーを再起動するのを忘れていました。私はサーバーを再起動し、それはうまくいきました。


それも私の場合でした。私は本当に複雑なことは何もしようとはしなかったので、それは何か愚かなことだと思いました。
Tashows

4

このエラーの理由は、現在のデータベース操作につながる誤った操作を実行できない前に、他のデータベースがあるためです(Googleの翻訳を使用して中国語を英語に翻訳します)。



2

ロールバックする必要があります。JDBC Postgresドライバーはかなり悪いです。ただし、トランザクションを保持し、そのエラーをロールバックする場合は、セーブポイントを使用できます。

try {
_stmt = connection.createStatement();
_savePoint = connection.setSavepoint("sp01");
_result = _stmt.executeUpdate(sentence) > 0;
} catch (Exception e){
 if (_savePoint!=null){
 connection.rollback(_savePoint);
}
}

詳細はこちら:

http://www.postgresql.org/docs/8.1/static/sql-savepoint.html


2

私は同じ問題を抱えていましたが、データベースに同じ名前のテーブルがあることに気付きました。それを削除した後、ファイルをインポートすることができました。


これは私の問題でした、私のためのテーブルは2つの異なるスキーマにまたがっていました。
トマト

0

これはPostgreSQLの非常に奇妙な動作であり、例外がキャッチされて明示的に無視されたため、「ユーザーにすべてを明示的にすることを強制するというPostgreSQLの哲学と一致していません」。したがって、この防御さえも成立しません。この場合のOracleの動作ははるかにユーザーフレンドリーで、(私としては)正しく動作します。開発者に選択の余地を残します。


0

これは、ボリュームのディスク領域が不足している場合に発生する可能性があります。


これが最も一般的な原因ではないことに気づきましたが、これはトラブルシューティングを求められたサーバーの場合です。したがって、これは潜在的な原因としてリストされるべきだと思います。
gregb


0

私はPostgresでJDBIを使用していて、同じ問題に遭遇しました。つまり、前のトランザクションのステートメントからの制約に違反した後、後続のステートメントは失敗します(ただし、20〜30秒待つと、問題はなくなります。 )。

調査の結果、JDBIで「手動」でトランザクションを実行していたことが問題であることがわかりました。つまり、ステートメントをBEGIN; ... COMMIT;で囲みました。そして、それは犯人であることが判明しました!

JDBI v2では、@ Transactionアノテーションを追加するだけで、@ SqlQueryまたは@SqlUpdate内のステートメントがトランザクションとして実行され、上記の問題は発生しなくなります。


0

私の場合、ファイルが破損していたため、このエラーが発生しました。ファイルのレコードを繰り返しているときに、同じエラーが発生しました。

将来的には誰にでも役立つでしょう。それがこの回答を投稿する唯一の理由です。


0

私は@Transactionalアノテーション付きの春を使用し、例外をキャッチし、いくつかの例外では3回再試行します。

posgresqlの場合、例外が発生すると、同じ接続を使用してこれ以上コミットすることはできません。最初にロールバックする必要があります。

私の場合は、を使用しDatasourceUtilsて現在の接続を取得し、connection.rollback()手動で呼び出します。そして、再呼び出しするメソッドrecruiveを呼び出します。




0

これを試して COMMIT;

pgadmin4で実行します。役立つかもしれません。前のコマンドが途中で停止することと関係があります


-1

分離レベルを繰り返し可能な読み取りからコミットされた読み取りに変更します。


-1

conn.setAutoCommit(false)をconn.setAutoCommit(true)に設定します

新しいトランザクションを開始する前にトランザクションをコミットします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.