sql >> Base de Datos >  >> RDS >> PostgreSQL

PSQLException:la transacción actual se aborta, los comandos se ignoran hasta el final del bloque de transacción

Recibí este error al usar Java y PostgreSQL haciendo una inserción en una tabla. Ilustraré cómo puedes reproducir este error:

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

Resumen:

La razón por la que obtiene este error es porque ingresó una transacción y una de sus consultas SQL falló, y se tragó esa falla y la ignoró. Pero eso no fue suficiente, ENTONCES usó esa misma conexión, usando la MISMA TRANSACCIÓN para ejecutar otra consulta. La excepción se produce en la segunda consulta formada correctamente porque está utilizando una transacción rota para realizar un trabajo adicional. PostgreSQL de forma predeterminada le impide hacer esto.

Estoy 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".

Mi controlador PostgreSQL es: postgresql-9.2-1000.jdbc4.jar

Usando la versión de Java: Java 1.7

Esta es la declaración de creación de tabla para ilustrar la excepción:

CREATE TABLE moobar
(
    myval   INT
);

El programa Java provoca el error:

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

}

El código anterior me produce este resultado:

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

Soluciones alternativas:

Tienes algunas opciones:

  1. La solución más simple:no estar en una transacción. Establezca connection.setAutoCommit(false); a connection.setAutoCommit(true); . Funciona porque entonces el SQL fallido simplemente se ignora como una declaración SQL fallida. Puede fallar en las declaraciones SQL todo lo que quiera y PostgreSQL no lo detendrá.

  2. Siga estando en una transacción, pero cuando detecte que el primer SQL ha fallado, retroceda/reinicie o confirme/reinicie la transacción. Luego puede continuar fallando tantas consultas SQL en esa conexión de base de datos como desee.

  3. No atrape e ignore la excepción que se genera cuando falla una instrucción SQL. Entonces el programa se detendrá en la consulta mal formada.

  4. Obtenga Oracle en su lugar, Oracle no lanza una excepción cuando falla una consulta en una conexión dentro de una transacción y continúa usando esa conexión.

En defensa de la decisión de PostgreSQL de hacer las cosas de esta manera... Oracle era haciéndote suave en el medio permitiéndote hacer cosas tontas y pasarlas por alto.