PSQLException: la transaction courante est annulée, les commandes ignorées jusqu'à la fin du bloc de transaction

je vois le stacktrace suivant (tronqué) dans le serveur.fichier journal de JBoss 7.1.1 Finale:

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'inspection du fichier journal de Postgres révèle les affirmations suivantes:

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

J'utilise L'Infinispan livré avec JBoss 7.1.1 Final, qui est 5.1.2.Final.

donc c'est ce que je pense qui se passe:

  • Infinispan tente d'exécuter le SELECT count(*)... déclaration afin de voir s'il existe des enregistrements dans la ISPN_MIXED_BINARY_TABLE_configCache ;
  • Postgres, pour une raison quelconque, n'aime pas cette déclaration.
  • Infinispan l'ignore et avance avec la déclaration CREATE TABLE .
  • Postgres barfs parce qu'il pense toujours qu'il s'agit de la même transaction, Qu'Infinispan n'a pas réussi à faire reculer, et cette transaction est tirée du premier énoncé SELECT count(*)... .

que signifie cette erreur et comment la contourner?

111
demandé sur Eric Leschinski 2012-05-01 19:11:22

14 réponses

j'ai eu cette erreur en utilisant Java et postgresql en faisant un insert sur une table. Je vais illustrer comment vous pouvez reproduire cette erreur:

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

résumé:

la raison pour laquelle vous obtenez cette erreur est parce que vous avez entré une transaction et une de vos requêtes SQL a échoué, et vous avez englouti cet échec et l'avez ignoré. Mais ce n'était pas assez, alors vous avez utilisé cette même connexion, en utilisant la même TRANSACTION pour exécuter une autre requête. L'exception est lancée sur la seconde, requête correctement formée parce que vous utilisez une transaction cassée pour faire du travail supplémentaire. Postgresql par défaut vous empêche de le faire.

j'utilise: 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".

mon pilote postgresql est: postgresql-9.2-1000.jdbc4.jar

utilisant la version java: Java 1.7

Voici la table créer l'énoncé pour illustrer l'Exception:

CREATE TABLE moobar
(
    myval   INT
);

Java program cause l'erreur:

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

}

le code ci-dessus produit cette sortie pour moi:

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

Solutions de contournement:

vous avez quelques options:

  1. la solution la plus simple: ne pas être dans une transaction. Mettez le connection.setAutoCommit(false); à connection.setAutoCommit(true); . Cela fonctionne car alors le SQL échoué est simplement ignoré comme une déclaration SQL échoué. Vous êtes invités à échouer les déclarations sql Tout ce que vous voulez et postgresql ne vous arrêtera pas.

  2. rester dans une transaction, mais quand vous détectez que le premier sql a échoué, soit le roll-back/Re-start ou commit/restart la transaction. Ensuite, vous peut continuer à échouer autant de requêtes sql sur cette connexion de base de données que vous le souhaitez.

  3. Ne pas les attraper et de les ignorer l'Exception est levée lorsqu'une instruction sql échoue. Puis le programme s'arrêtera sur la requête malformée.

  4. obtenir Oracle à la place, Oracle ne jette pas une exception lorsque vous échouez une requête sur une connexion dans une transaction et continuer à utiliser cette connexion.

pour la défense de postgresql, de sa décision de faire les choses de cette façon... Oracle était vous rendant doux au milieu de vous laisser faire des choses stupides et de le surplomber.

146
répondu Eric Leschinski 2013-10-08 16:49:17

Vérifiez la sortie avant l'énoncé qui a causé current transaction is aborted . Cela signifie généralement que la base de données a jeté une exception que votre code avait ignorée et maintenant s'attend à ce que les prochaines requêtes pour retourner certaines données.

donc vous avez maintenant un décalage d'état entre votre application, qui considère que les choses sont bonnes, et la base de données, qui vous oblige à revenir en arrière et redémarrer votre transaction dès le début.

vous devez attraper tous les exceptions et les opérations de réduction dans de tels cas.

Voici une question similaire.

18
répondu vyegorov 2017-05-23 12:26:09

je pense que la meilleure solution est d'utiliser java.SQL.Point de sauvegarde.

avant d'exécuter la requête qui peut lancer SQLException utiliser la connexion de méthode.setSavepoint () et si l'exception sera lancer, vous n'aurez qu'à revenir à cette transaction savepoint et non pas à la totalité de la transaction.

exemple de code:

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

   }
}
7
répondu Michał Orliński 2015-02-21 00:30:19

dans Ruby on Rails PG, j'avais créé une migration, migré ma DB, mais oublié de redémarrer mon serveur de développement. J'ai redémarré mon serveur et ça a fonctionné.

5
répondu thedanotto 2016-02-13 05:27:53

la raison de cette erreur est qu'Il ya une autre base de données avant que l'opération erronée conduit à l'exploitation de la base de données actuelle ne peut pas être effectuée, j'utilise google translation pour traduire mon chinois en anglais փ 151910920"

3
répondu 管浩浩 2017-06-09 02:37:53

la question a été corrigée dans Infinispan 5.1.5.CR1: ISPN-2023

2
répondu Dan Berindei 2012-05-30 10:26:13

vous devez reculer. Le pilote JDBC Postgres est assez mauvais. Mais si vous voulez garder votre transaction, et juste faire reculer cette erreur, vous pouvez utiliser des savepoints:

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

pour en savoir plus:

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

2
répondu Mariano L 2015-11-04 05:16:12

j'ai eu le MÊME PROBLÈME MAIS j'ai réalisé qu'il y avait une table avec le même nom dans la base de données. Après avoir supprimé cela, j'ai pu importer le fichier.

1
répondu S.Perera 2018-02-27 23:44:54

c'est un comportement très étrange de PostgreSQL, il n'est même pas "en ligne avec la philosophie de PostgreSQL de forcer l'utilisateur à tout rendre explicite"-comme l'exception a été attrapé et ignoré explicitement. Ainsi, même cette défense ne tient pas. Oracle dans ce cas se comporte beaucoup plus convivial et (comme pour moi) correctement - il laisse un choix du développeur.

0
répondu al0 2014-01-15 15:19:23

Cela peut se produire si vous êtes hors de l'espace disque sur le volume.

0
répondu gregb 2015-05-11 19:34:34

je viens de rencontrer la même erreur. J'ai pu comprendre la cause profonde en activant le log_statement et log_min_error_statement dans mon PostgreSQL local.

j'ai Appelé ce

0
répondu virtualpathum 2017-05-23 12:10:11

j'utilise Jdbi avec Postgres, et j'ai rencontré le même problème, c'est-à-dire qu'après une violation d'une contrainte d'une déclaration de transaction précédente, les déclarations suivantes échoueraient (mais après que j'ai attendu un certain temps, disons 20-30 secondes, le problème disparaît).

après quelques recherches, j'ai trouvé que le problème était que je faisais la transaction" manuellement " dans mon JDBI, i.e. j'ai entouré mes déclarations avec BEGIN;...S'ENGAGER; et il s'avère être le coupable!

dans JDBI v2, je peux juste ajouter l'annotation @Transaction, et les déclarations dans @SqlQuery ou @SqlUpdate seront exécutées comme une transaction, et le problème mentionné ci-dessus ne se produit plus!

0
répondu Qinwei Gong 2017-08-28 22:39:38

il y a eu des travaux sur le conducteur JDBC postgresql, liés à ce comportement:

voir https://github.com/pgjdbc/pgjdbc/pull/477

il est maintenant possible, en mettant

autosave=always
dans la connexion (voir https://jdbc.postgresql.org/documentation/head/connect.html ) pour éviter le syndrôme "transaction en cours est annulée".

frais généraux la manipulation d'un savepoint autour de l'exécution de l'instruction est maintenue très basse (voir lien ci-dessus pour plus de détails).
0
répondu thierry masson 2018-02-13 16:28:03

changer le niveau d'isolement de Read reproductible à READ committed.

-1
répondu ericj 2015-01-24 14:46:13