webentwicklung-frage-antwort-db.com.de

PSQLException: Die aktuelle Transaktion wird abgebrochen, Befehle werden bis zum Ende der Transaktionssperre ignoriert

Ich sehe das folgende (abgeschnittene) Stacktrace in der server.log-Datei von JBoss 7.1.1 Final:

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

Das Überprüfen der Postgres-Protokolldatei zeigt die folgenden Anweisungen:

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

Ich verwende den Infinispan, der mit JBoss 7.1.1 Final ausgeliefert wurde. Dies ist 5.1.2.Final.

Das ist also, was ich denke, passiert:

  • Infinispan versucht, die Anweisung SELECT count(*)... auszuführen, um festzustellen, ob der ISPN_MIXED_BINARY_TABLE_configCache Datensätze enthält.
  • Aus irgendeinem Grund mag Postgres diese Aussage nicht.
  • Infinispan ignoriert dies und setzt die CREATE TABLE-Anweisung fort.
  • Postgres wird gesperrt, da es sich nach wie vor um dieselbe Transaktion handelt, die Infinispan nicht zurücksetzen konnte, und diese Transaktion wird aus der ersten SELECT count(*)...-Anweisung abgeleitet.

Was bedeutet dieser Fehler und wie kann ich ihn umgehen?

118
Jimidy

Ich habe diesen Fehler mit Java und Postgresql beim Einfügen in eine Tabelle erhalten. Ich werde veranschaulichen, wie Sie diesen Fehler reproduzieren können:

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

Zusammenfassung:

Sie erhalten diesen Fehler, weil Sie eine Transaktion eingegeben haben und eine Ihrer SQL-Abfragen fehlgeschlagen ist. Sie haben diesen Fehler verschluckt und ignoriert. Aber das war noch nicht genug. DANN haben Sie dieselbe Verbindung benutzt und mit SAME TRANSACTION eine weitere Abfrage ausgeführt. Die Ausnahme wird bei der zweiten, korrekt gebildeten Abfrage ausgelöst, weil Sie eine fehlerhafte Transaktion verwenden, um zusätzliche Arbeit auszuführen. Postgresql hält Sie standardmäßig davon ab.

Ich verwende: 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".

Mein Postgresql-Treiber ist: postgresql-9.2-1000.jdbc4.jar

Java-Version verwenden: Java 1.7

Hier ist die Tabelle create Anweisung, um die Ausnahme zu veranschaulichen:

CREATE TABLE moobar
(
    myval   INT
);

Java-Programm verursacht den Fehler:

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();
    }   

}

Der obige Code erzeugt diese Ausgabe für mich:

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

Problemumgehungen:

Sie haben einige Möglichkeiten:

  1. Einfachste Lösung: Seien Sie nicht in einer Transaktion. Stellen Sie connection.setAutoCommit(false); auf connection.setAutoCommit(true);. Es funktioniert, weil dann die fehlgeschlagene SQL als fehlgeschlagene SQL-Anweisung ignoriert wird. Sie können SQL-Anweisungen nicht ausführen, wenn Sie möchten, und Postgresql wird Sie nicht aufhalten.

  2. Bleiben Sie in einer Transaktion. Wenn Sie jedoch feststellen, dass die erste SQL-Datenbank fehlgeschlagen ist, müssen Sie entweder die Transaktion rückgängig machen oder erneut starten oder die Transaktion festschreiben/erneut starten. Dann können Sie so viele SQL-Abfragen für diese Datenbankverbindung nicht mehr ausführen, wie Sie möchten.

  3. Fangen und ignorieren Sie nicht die Ausnahme, die ausgelöst wird, wenn eine SQL-Anweisung fehlschlägt. Dann stoppt das Programm bei der fehlerhaften Abfrage.

  4. Rufen Sie stattdessen Oracle ab. Oracle löst keine Ausnahme aus, wenn Sie eine Abfrage für eine Verbindung innerhalb einer Transaktion fehlschlagen und diese Verbindung weiterhin verwenden. 

Zur Verteidigung der Entscheidung von postgresql, Dinge auf diese Weise zu tun ... Oracle war macht Sie weich in der Mitte, lässt Sie dumme Sachen machen und übersieht es.

157
Eric Leschinski

Überprüfen Sie die Ausgabe vor der Anweisung, die current transaction is aborted verursacht hat. Dies bedeutet in der Regel, dass die Datenbank eine Ausnahme ausgelöst hat, die Ihr Code ignoriert hat, und erwartet, dass nächste Abfragen einige Daten zurückgeben.

Sie haben also einen Statusunterschied zwischen Ihrer Anwendung, die die Dinge für in Ordnung hält, und der Datenbank, die erfordert, dass Sie Ihre Transaktion von Anfang an zurücksetzen und neu starten.

In diesem Fall sollten Sie alle Ausnahmen und Rollback-Transaktionen abfangen.

Hier ist ein ähnliches Problem.

19
vyegorov

Ich denke, dass die beste Lösung Java.sql.Savepoint ist.

Bevor Sie eine Abfrage ausführen, die SQLException auslösen kann, verwenden Sie die Methode Connection.setSavepoint (). Wenn eine Exception ausgelöst wird, müssen Sie nur auf diesen Sicherungspunkt zurücksetzen und nicht alle Transaktionen zurücksetzen.

Beispielcode:

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

In Ruby on Rails PG hatte ich eine Migration erstellt, meine Datenbank migriert, aber vergessen, meinen Entwicklungsserver neu zu starten. Ich habe meinen Server neu gestartet und es hat funktioniert.

5
thedanotto

Der Grund für diesen Fehler ist, dass es andere Datenbanken gibt, bevor die falsche Operation dazu geführt hat, dass die aktuelle Datenbankoperation nicht durchgeführt werden kann.

3
管浩浩

Sie müssen einen Rollback ausführen. Der JDBC-Postgres-Treiber ist ziemlich schlecht. Wenn Sie jedoch Ihre Transaktion beibehalten und nur diesen Fehler zurücksetzen möchten, können Sie Sicherungspunkte verwenden:

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

Lesen Sie hier mehr:

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

2
Mariano L

Das Problem wurde in Infinispan 5.1.5.CR1 behoben: ISPN-2023

2
Dan Berindei

Der Postgresql-JDBC-Treiber hat einige Arbeit geleistet, die sich auf dieses Verhalten bezieht:
siehe https://github.com/pgjdbc/pgjdbc/pull/477

Es ist jetzt durch Einstellung möglich 

autosave = immer
in der Verbindung (siehe https://jdbc.postgresql.org/documentation/head/connect.html ), um das Syndrom "Aktuelle Transaktion abgebrochen" zu vermeiden.
Der Aufwand aufgrund der Verarbeitung eines Sicherungspunkts um die Ausführung der Anweisung wird sehr gering gehalten (siehe Link oben für Details).

2
thierry masson

Ich hatte das gleiche Problem, stellte jedoch fest, dass eine Tabelle mit demselben Namen in der Datenbank vorhanden ist. Nach dem Löschen konnte ich die Datei importieren.

1
S.Perera

Dies ist ein sehr seltsames Verhalten von PostgreSQL, es entspricht sogar nicht der PostgreSQL-Philosophie, den Benutzer dazu zu zwingen, alles explizit zu machen. Also auch diese Verteidigung hält nicht aus. Oracle verhält sich in diesem Fall viel benutzerfreundlicher und (für mich) korrekt - es lässt dem Entwickler die Wahl.

0
al0

Ich stoße gerade den gleichen Fehler. Ich konnte die Hauptursache herausfinden, indem ich in meiner lokalen PostgreSQL die Option log_statement und log_min_error_statement aktiviere. 

Ich verwies das

0
virtualpathum

Setzen Sie conn.setAutoCommit (false) auf conn.setAutoCommit (true).

Übernehmen Sie die Transaktionen, bevor Sie eine neue initiieren.

0
abinash sahoo

Ich verwende JDBI mit Postgres und bin auf das gleiche Problem gestoßen, dh nach einem Verstoß gegen eine Einschränkung durch eine Anweisung der vorherigen Transaktion würden nachfolgende Anweisungen fehlschlagen (aber nachdem ich eine Weile gewartet habe, etwa 20 bis 30 Sekunden, geht das Problem weg ).

Nach einiger Recherche stellte ich fest, dass das Problem darin bestand, dass ich die Transaktion "manuell" in meiner JDBI durchführte, d. H. Meine Anweisungen mit BEGIN umgeben; ... COMMIT; und es stellt sich heraus, dass es der Täter ist!

In JDBI v2 kann ich einfach die @Transaction-Annotation hinzufügen. Die Anweisungen in @SqlQuery oder @SqlUpdate werden als Transaktion ausgeführt und das oben genannte Problem tritt nicht mehr auf!

0
Qinwei Gong

Dies kann passieren, wenn auf dem Volume nicht genügend Speicherplatz vorhanden ist.

0
gregb