PSQLEException: huidige transactie wordt afgebroken, opdrachten genegeerd tot einde transactieblok

Ik zie de volgende (afgekorte) stacktrace in het server.log-bestand van 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

Inspectie van het logbestand van Postgres onthult de volgende verklaringen:

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

Ik gebruik de Infinispan die bij JBoss 7.1.1 Final wordt geleverd, wat 5.1.2.Final is.

Dus dit is wat ik denk dat er gebeurt:

  • Infinispan probeert de instructie SELECT count(*)...uit te voeren om te zien of er records zijn in de ISPN_MIXED_BINARY_TABLE_configCache;
  • Postgres houdt om de een of andere reden niet van deze uitspraak.
  • Infinispan negeert dit en gaat door met het CREATE TABLEstatement.
  • Postgres hapert omdat het nog steeds denkt dat het dezelfde transactie is die Infinispan niet heeft teruggedraaid, en deze transactie wordt verwijderd vanaf de eerste SELECT count(*)...-instructie.
  • >

Wat betekent deze fout en enig idee hoe je er omheen kunt werken?


Antwoord 1, autoriteit 100%

Ik kreeg deze fout bij het gebruik van Java en PostgreSQL bij het invoegen op een tabel. Ik zal illustreren hoe u deze fout kunt reproduceren:

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

Samenvatting:

De reden dat je deze foutmelding krijgt is omdat je een transactie hebt ingevoerd en een van je SQL-query’s is mislukt, en je hebt die fout opgeslokt en genegeerd. Maar dat was niet genoeg, DAN gebruikte je dezelfde verbinding en gebruikte DEZELFDE TRANSACTIE om een andere query uit te voeren. De uitzondering wordt gegenereerd op de tweede, correct gevormde query omdat u een verbroken transactie gebruikt om extra werk te doen. PostgreSQL zorgt er standaard voor dat u dit niet doet.

Ik gebruik: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".

Mijn PostgreSQL-stuurprogramma is:postgresql-9.2-1000.jdbc4.jar

Java-versie gebruiken:Java 1.7

Hier is de tabel create statement om de Exception te illustreren:

CREATE TABLE moobar
(
    myval   INT
);

Java-programma veroorzaakt de fout:

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

De bovenstaande code produceert deze uitvoer voor mij:

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

Oplossingen:

Je hebt een paar opties:

  1. Eenvoudigste oplossing: doe geen transactie. Stel connection.setAutoCommit(false);in op connection.setAutoCommit(true);. Het werkt omdat de mislukte SQL dan gewoon wordt genegeerd als een mislukte SQL-instructie. U bent van harte welkom om alle SQL-instructies te laten mislukken en PostgreSQL zal u niet stoppen.

  2. Blijf in een transactie, maar wanneer u merkt dat de eerste SQL is mislukt, moet u de transactie terugdraaien/opnieuw starten of vastleggen/herstarten. Dan kunt u doorgaan met het mislukken van zoveel SQL-query’s op die databaseverbinding als u wilt.

  3. Vang en negeer de uitzondering die wordt gegenereerd wanneer een SQL-instructie mislukt, niet. Dan stopt het programma bij de misvormde zoekopdracht.

  4. Neem in plaats daarvan Oracle, Oracle genereert geen uitzondering wanneer u een query op een verbinding binnen een transactie mislukt en die verbinding blijft gebruiken.

Ter verdediging van de beslissing van PostgreSQL om de dingen op deze manier te doen… Oracle maakteje zacht in het midden door je domme dingen te laten doen en het over het hoofd te zien.


Antwoord 2, autoriteit 16%

Controleer de uitvoer vóórde verklaring die ervoor zorgde dat current transaction is aborted. Dit betekent meestal dat de database een uitzondering heeft gegenereerd die uw code had genegeerd en nu verwacht dat de volgende query’s wat gegevens zullen retourneren.

Dus je hebt nu een status-mismatch tussen je applicatie, die van mening is dat alles in orde is, en de database, waardoor je de transactie vanaf het begin moet terugdraaien en opnieuw moet starten.

In dergelijke gevallen moet u alle uitzonderingen opvangen en transacties terugdraaien.

Dit is een soortgelijk probleem.


Antwoord 3, autoriteit 7%

Ik denk dat de beste oplossing is om java.sql.Savepointte gebruiken.

Voordat u een query uitvoert die throw SQLExceptionkan veroorzaken, gebruikt u de methode Connection.setSavepoint(), en als er een uitzondering wordt gegenereerd, kunt u alleen terugdraaien naar dit opslagpunt, niet de hele transactie.

Voorbeeldcode:

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

Antwoord 4, autoriteit 3%

Er is wat werk verricht aan het postgresql JDBC-stuurprogramma, gerelateerd aan dit gedrag:
zie https://github.com/pgjdbc/pgjdbc/pull/477

Het is nu mogelijk door

autosave=always

in te stellen in de verbinding (zie https://jdbc.postgresql.org/documentation/head/connect.html) om het ‘huidige transactie is afgebroken’-syndroom te voorkomen.
Overhead vanwege het verwerken van een opslagpunt rond de uitvoering van de instructie wordt zeer laag gehouden (zie link hierboven voor details).


Antwoord 5, autoriteit 2%

In Ruby on Rails PG had ik een migratie gemaakt, mijn DB gemigreerd, maar vergat ik mijn ontwikkelserver opnieuw op te starten. Ik heb mijn server opnieuw opgestart en het werkte.


Antwoord 6, autoriteit 2%

De reden voor deze fout is dat er een andere database is voordat de verkeerde bewerking ertoe heeft geleid dat de huidige databasebewerking niet kan worden uitgevoerd(ik gebruik Google-vertaling om mijn Chinees naar het Engels te vertalen)


Antwoord 7, autoriteit 2%

Probeer deze COMMIT;

Ik voer dat uit in pgadmin4. Het kan helpen.
Het heeft te maken met het voortijdig stoppen van het vorige commando


Antwoord 8

Je moet terugdraaien. De JDBC Postgres-driver is behoorlijk slecht. Maar als u uw transactie wilt behouden en die fout gewoon wilt terugdraaien, kunt u spaarpunten gebruiken:

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

Lees hier meer:

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


Antwoord 9

Het probleem is opgelost in Infinispan 5.1.5.CR1: ISPN-2023


Antwoord 10

Ik had hetzelfde probleem, maar realiseerde me toen dat er een tabel met dezelfde naam in de database staat. Nadat ik dat had verwijderd, kon ik het bestand importeren.


Antwoord 11

Dit kan gebeuren als u onvoldoende schijfruimte op het volume heeft.


Antwoord 12

Dit is heel raar gedrag van PostgreSQL, het is zelfs niet “in lijn met de PostgreSQL-filosofie om de gebruiker te dwingen alles expliciet te maken” – aangezien de uitzondering expliciet werd opgevangen en genegeerd. Dus zelfs deze verdediging gaat niet op. Oracle gedraagt zich in dit geval veel gebruiksvriendelijker en (wat mij betreft) correct – het laat een keuze aan de ontwikkelaar.


Antwoord 13

Ik kom net dezelfde fout tegen. Ik kon de oorzaak achterhalen door de log_statementen log_min_error_statementin mijn lokale PostgreSQL.

Ik heb ditdoorverwezen


Antwoord 14

Ik gebruik JDBI met Postgres en kwam hetzelfde probleem tegen, dat wil zeggen dat na een schending van een beperking van een verklaring van een eerdere transactie, de volgende verklaringen zouden mislukken (maar nadat ik een tijdje had gewacht, zeg 20-30 seconden, probleem verdwijnt).

Na wat onderzoek ontdekte ik dat het probleem was dat ik transacties “handmatig” uitvoerde in mijn JDBI, d.w.z. ik omringde mijn verklaringen met BEGIN;…COMMIT; en het blijkt de boosdoener te zijn!

In JDBI v2 kan ik gewoon @Transaction annotatie toevoegen, en de statements binnen @SqlQuery of @SqlUpdate worden uitgevoerd als een transactie, en het bovengenoemde probleem doet zich niet meer voor!


Antwoord 15

In mijn geval kreeg ik deze foutmelding omdat mijn bestand corrupt was. Tijdens het herhalen van de records van bestanden gaf het me dezelfde fout.

Misschien zal het in de toekomst voor iedereen nuttig zijn. Dat is de enige reden om dit antwoord te posten.


Antwoord 16

Ik gebruik spring met @Transactionalannotatie, en ik vang de uitzondering en voor sommige uitzonderingen zal ik het 3 keer opnieuw proberen.

Voor posgresql, wanneer u een uitzondering krijgt, kunt u dezelfde verbinding niet meer gebruiken om vast te leggen. U moet eerst terugdraaien.

Voor mijn geval gebruik ik de DatasourceUtilsom de huidige verbinding te krijgen en roep connection.rollback()handmatig aan. En roep de methode recruive aan om het opnieuw te proberen.


Antwoord 17

Ik werkte met spring boot jpa en herstelde door te implementeren
@EnableTransactionManagement

Bijgevoegd bestand kan u helpen.


Antwoord 18

Verander het isolatieniveau van herhaalbaar lezen naar lezen vastgelegd.


Antwoord 19

Stel conn.setAutoCommit(false) in op conn.setAutoCommit(true)

Voer de transacties uit voordat u een nieuwe start.


Antwoord 20

Ik werkte met spring boot jpa en herstelde door te implementeren
@EnableTransactionManagement

Bijgevoegd bestand kan je misschien helpen.voer hier de afbeeldingsbeschrijving in

Other episodes