PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

PSQLException :la transaction en cours est abandonnée, les commandes sont ignorées jusqu'à la fin du bloc de transaction

J'ai eu cette erreur en utilisant Java et PostgreSQL en faisant une insertion 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 que vous avez entré une transaction et que l'une de vos requêtes SQL a échoué, et vous avez englouti cet échec et l'avez ignoré. Mais cela ne suffisait pas, ALORS vous avez utilisé cette même connexion, en utilisant la MÊME TRANSACTION pour exécuter une autre requête. L'exception est levée sur la deuxième requête correctement formée, car vous utilisez une transaction interrompue pour effectuer un travail supplémentaire. PostgreSQL par défaut vous empêche de faire cela.

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

Utilisation de la version Java : Java 1.7

Voici l'instruction de création de table pour illustrer l'exception :

CREATE TABLE moobar
(
    myval   INT
);

Le programme Java provoque 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 :

Vous avez plusieurs options :

  1. Solution la plus simple :ne pas participer à une transaction. Définissez le connection.setAutoCommit(false); à connection.setAutoCommit(true); . Cela fonctionne car le SQL défaillant est simplement ignoré en tant qu'instruction SQL défaillante. Vous pouvez faire échouer les instructions SQL autant que vous voulez et PostgreSQL ne vous arrêtera pas.

  2. Restez dans une transaction, mais lorsque vous détectez que le premier SQL a échoué, annulez/redémarrez ou validez/redémarrez la transaction. Ensuite, vous pouvez continuer à échouer autant de requêtes SQL sur cette connexion à la base de données que vous le souhaitez.

  3. N'interceptez pas et n'ignorez pas l'exception qui est levée lorsqu'une instruction SQL échoue. Ensuite, le programme s'arrêtera sur la requête malformée.

  4. Obtenez Oracle à la place, Oracle ne lève pas d'exception lorsque vous échouez à une requête sur une connexion dans une transaction et continuez à utiliser cette connexion.

Pour défendre la décision de PostgreSQL de faire les choses de cette façon... Oracle était vous rendant doux au milieu vous permettant de faire des trucs stupides et de les négliger.