PSQLException: Die aktuelle Transaktion wird abgebrochen, Befehle werden bis zum Ende des Transaktionsblocks ignoriert

150

In der Datei server.log von JBoss 7.1.1 Final wird die folgende (abgeschnittene) Stapelverfolgung angezeigt:

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 Aussagen:

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 das mit JBoss 7.1.1 Final gelieferte Infinispan, das 5.1.2.Final ist.

Ich denke also, dass dies geschieht:

  • Infinispan versucht, die SELECT count(*)...Anweisung auszuführen, um festzustellen, ob Datensätze in der Datei vorhanden sind ISPN_MIXED_BINARY_TABLE_configCache.
  • Postgres mag diese Aussage aus irgendeinem Grund nicht.
  • Infinispan ignoriert dies und macht mit der CREATE TABLEAussage weiter.
  • Postgres barfs, weil es immer noch denkt, dass es sich um dieselbe Transaktion handelt, die Infinispan nicht zurückgesetzt hat, und diese Transaktion aus der ersten SELECT count(*)...Anweisung hervorgeht.

Was bedeutet dieser Fehler und wie kann man ihn umgehen?

Jimidy
quelle
Nur wenn du hierher gekommen bist wie ich auf der Suche nach dem oben genannten PSQLException: current transaction is aborted...( 25P02) und vielleicht auch JPAoder Hibernate. Schließlich lag es an unserer (netten!) Logback- Nutzung, die mit einem toString()überladenen DAO-Objekt gespeist wurde , das den Fehler verursachte und gut verschluckt wurde (aber von mir versehentlich unbemerkt blieb): log.info( "bla bla: {}", obj )produziert bla bla: [FAILED toString()]. Wenn Sie log.info( "bla bla: {}", String.valueOf( obj )es so ändern, dass es nullsicher ist, es aber nicht verschluckt wird und die Transaktion offen bleibt, schlägt dies bei einer nicht verwandten Abfrage fehl.
Andreas Dietrich
Ich habe die gleiche Art von Fehler bekommen. Ich musste die Verbindung vor dem SQL freigeben. Mein Code war connection.commit ()
md. ariful ahsan

Antworten:

203

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:

Der Grund, warum Sie diesen Fehler erhalten, ist, dass Sie eine Transaktion eingegeben haben und eine Ihrer SQL-Abfragen fehlgeschlagen ist. Sie haben diesen Fehler verschlungen und ignoriert. Aber das war nicht genug, DANN haben Sie dieselbe Verbindung verwendet und mit der GLEICHEN TRANSAKTION eine weitere Abfrage ausgeführt. Die Ausnahme wird bei der zweiten, korrekt geformten Abfrage ausgelöst, da Sie eine fehlerhafte Transaktion verwenden, um zusätzliche Arbeit zu erledigen. Postgresql hindert Sie standardmäßig daran.

Ich benutze: 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

Verwenden der Java-Version: Java 1.7

Hier ist die Anweisung zum Erstellen der Tabelle, 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 das connection.setAutoCommit(false);auf connection.setAutoCommit(true);. Es funktioniert, weil dann das fehlgeschlagene SQL einfach als fehlgeschlagene SQL-Anweisung ignoriert wird. Sie können gerne SQL-Anweisungen verfehlen, was Sie wollen, und postgresql wird Sie nicht aufhalten.

  2. Bleiben Sie in einer Transaktion, aber wenn Sie feststellen, dass die erste SQL fehlgeschlagen ist, können Sie die Transaktion entweder zurücksetzen / neu starten oder festschreiben / neu starten. Anschließend können Sie weiterhin so viele SQL-Abfragen für diese Datenbankverbindung fehlschlagen, wie Sie möchten.

  3. Erfassen 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. Holen Sie sich stattdessen Oracle. Oracle löst keine Ausnahme aus, wenn Sie eine Abfrage für eine Verbindung innerhalb einer Transaktion nicht bestehen und diese Verbindung weiterhin verwenden.

In Verteidigung der Entscheidung der postgresql Dinge auf diese Weise zu tun ... Oracle wurde , dass Sie weicht in der Mitte so dass Sie dumm Sachen tun und mit Blick auf sich.

Eric Leschinski
quelle
10
Lol @ Option 4 ... Ich habe in Oracle ziemlich viel entwickelt und vor kurzem angefangen, Postgres zu verwenden ... es ist wirklich ärgerlich, dass Postgres dies tut, und jetzt müssen wir einen großen Teil unseres Programms, das wir haben, wirklich neu schreiben portieren von Oracle nach Postgres. Warum gibt es keine Option wie die erste, mit der es sich wie Oracle verhält, jedoch ohne das automatische Festschreiben ?
ADTC
2
Nach einigen Versuchen wurde festgestellt, dass Option 2 dem Oracle-Verhalten am nächsten kommt. Wenn Sie mehrere Updates ausgeben müssen und ein Fehler nachfolgende Updates nicht stoppen sollte, rufen Sie einfach das rollback()an, Connectionwenn ein SQLExceptionabgefangen wird. [ Wie auch immer, ich erkannte, dass dies im Einklang mit der PostgreSQL-Philosophie steht, den Benutzer zu zwingen, alles explizit zu machen, während Oracle die Philosophie hat, sich implizit um viele Dinge zu kümmern.]
ADTC
2
Option 2 enthält eine unmögliche Verzweigung or commit/restart the transaction. Wie ich sehen kann, gibt es keine Möglichkeit, nach einer Ausnahme ein Commit durchzuführen. Wenn ich versuche zu verpflichten - PostgreSQL dorollback
turbanoff
1
Ich kann das von @turbanoff aufgeworfene Problem bestätigen. Dies kann auch direkt mit reproduziert werden psql. (1) eine Transaktion starten, (2) einige gültige Anweisungen ausgeben, (3) eine ungültige Anweisung ausgeben, (4) festschreiben -> psql wird zurücksetzen, anstatt festzuschreiben.
Alphaaa
1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl eine interessante Diskussion zu diesem Thema. Wenn dieses Problem durch eine Einschränkungsverletzung ausgelöst wird, empfehlen die PostgreSQL-Entwickler, vorab nach einem Konflikt zu suchen (Abfrage vor dem Aktualisieren / Einfügen) oder zu verwenden savepoints, um zum Punkt vor dem Aktualisieren / Einfügen zurückzukehren. Beispielcode finden Sie unter stackoverflow.com/a/28640557/14731 .
Gili
27

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

Sie haben jetzt eine Statusinkongruenz zwischen Ihrer Anwendung, die die Dinge für in Ordnung hält, und der Datenbank, die es erforderlich macht, dass Sie Ihre Transaktion von Anfang an zurücksetzen und neu starten.

In solchen Fällen sollten Sie alle Ausnahmen und Rollback-Transaktionen abfangen.

Hier ist ein ähnliches Problem.

vyegorov
quelle
Das ist großartig, außer in diesem Fall wäre es Infinispan, eine Bibliothek eines Drittanbieters, die mit Postgres spricht, und nicht mein Code.
Jimidy
Nun, die Situation ist immer noch dieselbe - die Transaktion muss zurückgesetzt werden. Überprüfen Sie möglicherweise, ob es eine neuere Version der Bibliothek gibt, die Sie verwenden, oder lösen Sie das Problem in ihrem Bug-Tracker aus. Wenn Sie genau SQLdas finden , was das Problem verursacht hat, haben Sie ein Feld, um das Problem mithilfe der PostgreSQL-Erweiterbarkeit zu beheben.
Vyegorov
Scheint, als hätten Sie meinen Verdacht bestätigt - ich werde mir jetzt die Infinispan 5.1.2-Quelle ansehen.
Jimidy
Um fair zu sein, gibt es in der TableManipulation-Klasse einen Try-Catch um den Versuch, select count (*) auszuführen. Möglicherweise löst der Postgres-Treiber keine der erwarteten Ausnahmen aus. Ich werde einen Debugger an JBoss anschließen, um mehr herauszufinden.
Jimidy
Der betreffende Infinispan-Code wurde in diesem Fehler vorgeschlagen: issue.jboss.org/browse/… Ich habe einen Debugger angehängt, der auf einer Live-JBoss 7.1.1-Instanz ausgeführt wird, und Postgres löst Ausnahmen an den richtigen Stellen aus. Vielleicht sind es die Anweisungen JdbcUtil.safeClose (), die ihren Job nicht machen. Ich werde es mit Infinispan ansprechen.
Jimidy
13

Ich denke, dass die beste Lösung die Verwendung von java.sql.Savepoint ist.

Bevor Sie eine Abfrage ausführen, die eine SQLException auslösen kann, verwenden Sie die Methode Connection.setSavepoint (). Wenn eine Ausnahme ausgelöst wird, wird nur ein Rollback auf diesen Sicherungspunkt durchgeführt, nicht alle Transaktionen werden zurückgesetzt.

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) {}

   }
}
Michał Orliński
quelle
Ich habe versehentlich irgendwie herabgestimmt, gerade erst bemerkt. War nicht beabsichtigt, ich kann nicht rückgängig machen, wenn die Antwort nicht bearbeitet wird.
Kerberos
Der Savepoint-Weg ist die eigentliche Lösung. Funktioniert für mich auch in der Umgebung von PHP, Doctrine2 und Postgres (9.5). Danke
Helvete
6

Im Zusammenhang mit diesem Verhalten wurden einige Arbeiten am postgresql-JDBC-Treiber durchgeführt:
siehe https://github.com/pgjdbc/pgjdbc/pull/477

Es ist jetzt möglich, durch Einstellen

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

Thierry Masson
quelle
5

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.

thedanotto
quelle
Das war auch mein Fall. Ich dachte, es sollte etwas Dummes sein, weil ich nicht wirklich versucht habe, etwas so Kompliziertes zu tun.
Tashows
4

Der Grund für diesen Fehler ist, dass es andere Datenbanken gibt, bevor die falsche Operation, die zur aktuellen Datenbankoperation geführt hat, nicht ausgeführt werden kann. (Ich verwende Google Translation, um mein Chinesisch ins Englische zu übersetzen.)

管 浩浩
quelle
2

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

Dan Berindei
quelle
2

Sie müssen ein Rollback durchführen. Der JDBC Postgres-Treiber ist ziemlich schlecht. Wenn Sie jedoch Ihre Transaktion beibehalten und diesen Fehler nur rückgängig machen 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

Mariano L.
quelle
2

Ich hatte das gleiche Problem, stellte dann aber fest, dass die Datenbank eine Tabelle mit demselben Namen enthält. Nach dem Löschen konnte ich die Datei importieren.

S.Perera
quelle
Dies war mein Problem, die Tabellen für mich waren über zwei verschiedene Schemata verteilt.
Tomate
0

Dies ist ein sehr seltsames Verhalten von PostgreSQL. Es entspricht nicht einmal der PostgreSQL-Philosophie, den Benutzer zu zwingen, alles explizit zu machen, da die Ausnahme explizit abgefangen und ignoriert wurde. Also auch diese Verteidigung hält nicht. Oracle verhält sich in diesem Fall viel benutzerfreundlicher und (wie für mich) korrekt - es überlässt dem Entwickler die Wahl.

al0
quelle
0

Dies kann passieren, wenn Sie nicht genügend Speicherplatz auf dem Volume haben.

gregb
quelle
Mir ist klar, dass dies nicht die häufigste Ursache ist, aber dies war auf einem Server der Fall, auf dem ich zur Fehlerbehebung aufgefordert wurde. Daher denke ich, dass dies als mögliche Ursache aufgeführt werden sollte.
Gregb
0

Ich verwende JDBI mit Postgres und bin auf dasselbe Problem gestoßen, dh nach einer Verletzung einer Einschränkung aus einer Anweisung der vorherigen Transaktion würden nachfolgende Anweisungen fehlschlagen (aber nachdem ich eine Weile gewartet habe, z. B. 20 bis 30 Sekunden, verschwindet das Problem ).

Nach einigen Recherchen stellte ich fest, dass das Problem darin bestand, dass ich die Transaktion in meinem JDBI "manuell" durchführte, dh meine Aussagen mit BEGIN umgab; ... COMMIT; und es stellt sich heraus, der Schuldige zu sein!

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

Qinwei Gong
quelle
0

In meinem Fall wurde dieser Fehler angezeigt, weil meine Datei beschädigt war. Beim Iterieren der Datensätze gab es den gleichen Fehler.

Vielleicht wird es in Zukunft jedem helfen. Das ist der einzige Grund, diese Antwort zu posten.

Bharti Rawat
quelle
0

Ich verwende spring mit @TransactionalAnnotation und fange die Ausnahme ab. In einigen Fällen werde ich es dreimal wiederholen.

Wenn für posgresql eine Ausnahme vorliegt, können Sie nicht mehr dieselbe Verbindung zum Festschreiben verwenden. Sie müssen zuerst ein Rollback durchführen.

In meinem Fall verwende ich die DatasourceUtils, um die aktuelle Verbindung connection.rollback()abzurufen und manuell anzurufen . Und der Aufruf der Methode rekrutiert, um es erneut zu versuchen.

Ysjiang
quelle
0

Ich habe mit Spring Boot JPA gearbeitet und durch Implementierung von @EnableTransactionManagement behoben

Die angehängte Datei kann Ihnen helfen.Geben Sie hier die Bildbeschreibung ein

Shahid Hussain Abbasi
quelle
0

Ich habe mit Spring Boot JPA gearbeitet und durch Implementierung von @EnableTransactionManagement behoben

Die angehängte Datei kann Ihnen helfen.

Shahid Hussain Abbasi
quelle
0

Versuche dies COMMIT;

Ich führe das in pgadmin4 aus. Es kann helfen. Dies hat damit zu tun, dass der vorherige Befehl vorzeitig gestoppt wurde

Phillip Kigenyi
quelle
-1

Ändern Sie die Isolationsstufe von wiederholbarem Lesen in festgeschriebenes Lesen.

ericj
quelle
-1

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

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

Abinash Sahoo
quelle