PSQLException: la transazione corrente viene interrotta, i comandi vengono ignorati fino alla fine del blocco della transazione


152

Sto vedendo il seguente stacktrace (troncato) nel file server.log di 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

L'ispezione del file di registro Postgres rivela le seguenti dichiarazioni:

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

Sto usando Infinispan fornito con JBoss 7.1.1 Final, che è 5.1.2.

Quindi questo è quello che penso stia accadendo:

  • Infinispan tenta di eseguire l' SELECT count(*)...istruzione per vedere se ci sono record in ISPN_MIXED_BINARY_TABLE_configCache;
  • A Postgres, per qualche motivo, questa frase non piace.
  • Infinispan lo ignora e prosegue con l' CREATE TABLEaffermazione.
  • Postgres barfs perché pensa ancora che sia la stessa transazione, che Infinispan non è riuscita a ripristinare, e questa transazione è derivata dalla prima SELECT count(*)...istruzione.

Cosa significa questo errore e qualche idea su come aggirarlo?


Solo se sei venuto qui come me alla ricerca di quanto sopra PSQLException: current transaction is aborted...( 25P02) e forse anche JPAo Hibernate. Alla fine è stato dovuto al nostro (bello!) Utilizzo del logback alimentato con un toString()oggetto DAO sovraccaricato che ha causato l'errore ed è stato deglutito (ma accidentalmente notato da me): log.info( "bla bla: {}", obj )prodotto bla bla: [FAILED toString()]. cambiandolo per log.info( "bla bla: {}", String.valueOf( obj )renderlo null-safe, ma non ingoiarlo e quindi lasciare aperta la transazione fallendo su una query non correlata.
Andreas Dietrich,

Stavo ottenendo lo stesso tipo di errore. Ho dovuto rilasciare la connessione prima di sql. Il mio codice era connection.commit ()
md. ariful ahsan,

Risposte:


203

Ho riscontrato questo errore usando Java e postgresql facendo un inserimento su un tavolo. Illustrerò come è possibile riprodurre questo errore:

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

Sommario:

Il motivo per cui viene visualizzato questo errore è perché è stata immessa una transazione e una delle query SQL non è riuscita e è stato assorbito tale errore e lo si è ignorato. Ma non era abbastanza, POI hai usato la stessa connessione, usando la STESSA TRANSAZIONE per eseguire un'altra query. L'eccezione viene generata nella seconda query correttamente formata perché si sta utilizzando una transazione non riuscita per eseguire ulteriori operazioni. Postgresql di default ti impedisce di farlo.

Sto usando: 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".

Il mio driver postgresql è: postgresql-9.2-1000.jdbc4.jar

Utilizzando la versione java: Java 1.7

Ecco l'istruzione table create per illustrare l'eccezione:

CREATE TABLE moobar
(
    myval   INT
);

Il programma Java causa l'errore:

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

}

Il codice sopra produce questo output per me:

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

soluzioni alternative:

Hai alcune opzioni:

  1. Soluzione più semplice: non essere in una transazione. Impostare connection.setAutoCommit(false);su connection.setAutoCommit(true);. Funziona perché l'SQL non riuscito viene semplicemente ignorato come un'istruzione sql non riuscita. Sei libero di fallire le istruzioni sql che vuoi e postgresql non ti fermerà.

  2. Rimanere in una transazione, ma quando si rileva che il primo sql non è riuscito, eseguire il rollback / riavviare o eseguire il commit / riavviare la transazione. Quindi puoi continuare a fallire quante query sql su quella connessione al database vuoi.

  3. Non catturare e ignorare l'eccezione generata quando un'istruzione sql ha esito negativo. Quindi il programma si arresterà sulla query non valida.

  4. Ottieni invece Oracle, Oracle non genera un'eccezione quando fallisci una query su una connessione all'interno di una transazione e continui a utilizzare quella connessione.

A difesa della decisione di postgresql di fare le cose in questo modo ... Oracle ti stava rendendo morbido nel mezzo, lasciandoti fare cose stupide e trascurandole.


10
Lol @ Opzione 4 ... Avevo fatto un bel po 'di sviluppo in Oracle e recentemente ho iniziato a usare Postgres ... è davvero fastidioso che Postgres faccia questo, e ora dobbiamo davvero riscrivere una grande parte del nostro programma che noi stanno effettuando il porting da Oracle a Postgres. Perché non esiste un'opzione come la prima per farlo funzionare come Oracle ma senza il commit automatico ?
ADTC

2
Dopo alcune prove, ho scoperto che l' opzione 2 è la più vicina al comportamento di Oracle. Se avete bisogno di rilasciare più aggiornamenti, e un fallimento non dovrebbe smettere di successivi aggiornamenti, è sufficiente chiamare rollback()il Connectionquando un SQLException'colto. [ Comunque mi sono reso conto che ciò è in linea con la filosofia PostgreSQL di costringere l'utente a rendere tutto esplicito, mentre Oracle ha la filosofia di occuparsi implicitamente di molte cose.]
ADTC

2
L'opzione 2 contiene un ramo impossibile or commit/restart the transaction. Come posso vedere, non c'è modo di impegnarsi dopo un'eccezione. Quando provo a impegnarmi - PostgreSQL dorollback
turbanoff,

1
Posso confermare il problema sollevato da @turbanoff. Questo può anche essere riprodotto direttamente con psql. (1) avvia una transazione, (2) rilascia alcune dichiarazioni valide, (3) rilascia una dichiarazione non valida, (4) commit -> psql eseguirà il rollback anziché il commit.
Alphaaa,

1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl un'interessante discussione su questo argomento. Se questo problema è innescato da una violazione del vincolo, gli sviluppatori PostgreSQL consigliano di verificare anticipatamente un conflitto (query prima dell'aggiornamento / inserimento) o di utilizzare savepointsper tornare al punto prima dell'aggiornamento / inserimento. Vedere stackoverflow.com/a/28640557/14731 per il codice di esempio.
Gili,

27

Controllare l'output prima dell'istruzione che ha causato current transaction is aborted. Ciò significa in genere che il database ha generato un'eccezione che il codice aveva ignorato e ora si aspetta che le query successive restituiscano alcuni dati.

Quindi ora c'è una discrepanza di stato tra l'applicazione, che considera le cose andate bene e il database, che richiede il rollback e il riavvio della transazione dall'inizio.

In tali casi è necessario rilevare tutte le eccezioni e le transazioni di rollback.

Ecco un problema simile.


È fantastico, tranne che in questo caso sarebbe Infinispan, una biblioteca di terze parti, che parlava con Postgres e non il mio codice.
Jimidy,

Bene, la situazione è sempre la stessa: la transazione deve essere ripristinata. Forse controlla se c'è una versione più recente della libreria che stai utilizzando o solleva il problema nel loro bug tracker. Se trovi l'esatto motivo SQLche ha causato il problema, avrai qualche campo per eliminare il problema usando l'estensibilità PostgreSQL.
vyegorov,

Sembra che tu abbia confermato i miei sospetti - esaminerò ora la fonte Infinispan 5.1.2.
Jimidy,

Ad essere onesti, nella classe TableManipulation, c'è un tentativo-catch intorno al tentativo di eseguire select count (*) .... Forse il driver Postgres non sta lanciando una delle eccezioni previste. Collegherò un debugger a JBoss per provare a scoprire di più.
Jimidy,

Il codice Infinispan in questione è stato suggerito in questo bug: issues.jboss.org/browse/… Ho collegato un debugger in esecuzione su un'istanza JBoss 7.1.1 live e Postgres sta gettando eccezioni nei posti giusti. Forse sono le dichiarazioni JdbcUtil.safeClose () che non stanno facendo il loro lavoro. Lo solleverò con Infinispan.
Jimidy,

13

Penso che la soluzione migliore sia utilizzare java.sql.Savepoint.

Prima di eseguire una query che può generare SQLException, utilizzare il metodo Connection.setSavepoint () e se verrà generata un'eccezione, si esegue il rollback solo a questo punto di salvataggio, non il rollback di tutte le transazioni.

Codice di esempio:

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

   }
}

Ho inavvertitamente annullato il voto in qualche modo, appena notato. Non è stato intenzionale, non posso annullare a meno che la risposta non venga modificata.
cerberos,

Il modo savepoint è la soluzione reale. Funziona per me anche in ambiente di PHP, Doctrine2 e Postgres (9.5). Grazie
helvete il

6

È stato svolto del lavoro sul driver JDBC postgresql, relativo a questo comportamento:
consultare https://github.com/pgjdbc/pgjdbc/pull/477

Ora è possibile, impostando

AutoSave = sempre
nella connessione (consultare https://jdbc.postgresql.org/documentation/head/connect.html ) per evitare il sindroma "transazione corrente interrotta".
Le spese generali dovute alla gestione di un punto di salvataggio intorno all'esecuzione dell'istruzione vengono mantenute molto basse (vedere il link sopra per i dettagli).


5

In Ruby on Rails PG, avevo creato una migrazione, migrato il mio DB, ma ho dimenticato di riavviare il mio server di sviluppo. Ho riavviato il mio server e ha funzionato.


Anche quello era il mio caso. Ho pensato che dovrebbe essere qualcosa di stupido, perché non ho davvero provato a fare qualcosa di così complicato.
Tashows,

4

Il motivo di questo errore è che ci sono altri database prima che l'operazione errata abbia portato all'operazione del database corrente non può essere eseguita (Uso la traduzione di Google per tradurre il mio cinese in inglese)



2

Devi eseguire il rollback. Il driver JDBC Postgres è piuttosto male. Ma se vuoi mantenere la tua transazione e semplicemente ripristinare quell'errore, puoi usare i punti di salvataggio:

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

Leggi di più qui:

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


2

Ho avuto lo stesso problema, ma poi ho capito che esiste una tabella con lo stesso nome nel database. Dopo aver eliminato che sono stato in grado di importare il file.


Questo era il mio problema, i tavoli per me erano su due diversi schemi.
pomodoro,

0

Questo è un comportamento molto strano di PostgreSQL, non è nemmeno "in linea con la filosofia PostgreSQL di costringere l'utente a rendere tutto esplicito" - poiché l'eccezione è stata colta e ignorata esplicitamente. Quindi anche questa difesa non regge. Oracle in questo caso si comporta in modo molto più intuitivo e (come per me) corretto - lascia una scelta allo sviluppatore.


0

Questo può accadere se lo spazio sul disco è insufficiente sul volume.


Mi rendo conto che questa non è la causa più comune, ma questo è stato il caso su un server che mi è stato chiesto di risolvere. Quindi penso che questo dovrebbe essere elencato come una potenziale causa.
Greg


0

Sto usando JDBI con Postgres e ho riscontrato lo stesso problema, ovvero dopo una violazione di un vincolo da una dichiarazione di transazione precedente, le dichiarazioni successive fallirebbero (ma dopo che aspetto un po ', diciamo 20-30 secondi, il problema scompare ).

Dopo alcune ricerche, ho scoperto che il problema era che stavo facendo una transazione "manualmente" nel mio JDBI, ovvero ho circondato le mie dichiarazioni con INIZIA; ... COMMIT; e risulta essere il colpevole!

In JDBI v2, posso semplicemente aggiungere l'annotazione @Transaction e le istruzioni all'interno di @SqlQuery o @SqlUpdate verranno eseguite come transazione e il problema sopra menzionato non si verifica più!


0

Nel mio caso stavo ricevendo questo errore perché il mio file era corrotto. Mentre ripetevo i record dei file, mi dava lo stesso errore.

Potrebbe essere in futuro aiuterà a chiunque. Questo è l'unico motivo per pubblicare questa risposta.


0

Uso la primavera con l' @Transactionalannotazione e prendo l'eccezione e per qualche eccezione riproverò 3 volte.

Per posgresql, quando si ottiene un'eccezione, non è possibile utilizzare la stessa connessione per eseguire il commit più. È necessario innanzitutto eseguire il rollback.

Nel mio caso, utilizzo il DatasourceUtilsper ottenere la connessione corrente e chiamare connection.rollback()manualmente. E chiama il metodo reclutare per riprovare.


0

Stavo lavorando con Spring Boot jpa e risolto implementando @EnableTransactionManagement

Il file allegato può aiutarti.inserisci qui la descrizione dell'immagine


0

Stavo lavorando con Spring Boot jpa e risolto implementando @EnableTransactionManagement

Il file allegato può aiutarti.


0

Prova questo COMMIT;

Lo eseguo in pgadmin4. Potrebbe essere d'aiuto. Ha a che fare con il comando precedente che si interrompe prematuramente


-1

Cambia il livello di isolamento dalla lettura ripetibile alla lettura impegnata.


-1

Impostare conn.setAutoCommit (false) su conn.setAutoCommit (true)

Effettua il commit delle transazioni prima di avviarne una nuova.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.