web-dev-qa-db-ja.com

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

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

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

121
Jimidy

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の決定を擁護するために... Oraclewasは真ん中を柔らかくして、物の言えないことをさせて見下ろしました。

166
Eric Leschinski

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

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

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

同様の問題があります。

21
vyegorov

最善の解決策は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) {}

   }
}
8

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

5
thedanotto

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

3
管浩浩

ロールバックする必要があります。 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
Mariano L

この問題は、Infinispan 5.1.5.CR1で修正されました。 ISPN-202

2
Dan Berindei

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

1
S.Perera

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

0
al0

同じエラーが発生しました。ローカルのPostgreSQLで log_statement および log_min_error_statement を有効にすることで、根本原因を突き止めることができました。

参照しました this

0
virtualpathum

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

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

0
abinash sahoo

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

いくつかの調査の後、私はJDBIで「手動で」トランザクションを行っていた、つまり、ステートメントをBEGIN; ... COMMIT;そして、それが犯人であることが判明しました!

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

0
Qinwei Gong

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

0
gregb