PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

PSQLException:a transação atual é abortada, comandos ignorados até o final do bloco de transação


Recebi este erro usando Java e PostgreSQL fazendo uma inserção em uma tabela. Vou ilustrar como você pode reproduzir este erro:
org.postgresql.util.PSQLException: ERROR: 
current transaction is aborted, commands ignored until end of transaction block

Resumo:

O motivo pelo qual você recebe esse erro é porque você inseriu uma transação e uma de suas consultas SQL falhou, e você engoliu essa falha e a ignorou. Mas isso não foi suficiente, ENTÃO você usou essa mesma conexão, usando a MESMA TRANSAÇÃO para executar outra consulta. A exceção é lançada na segunda consulta corretamente formada porque você está usando uma transação quebrada para fazer trabalho adicional. O PostgreSQL por padrão impede você de fazer isso.

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

Meu driver PostgreSQL é: postgresql-9.2-1000.jdbc4.jar

Usando a versão Java: Java 1.7

Aqui está a instrução de criação de tabela para ilustrar a exceção:
CREATE TABLE moobar
(
    myval   INT
);

O programa Java causa o erro:
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();
    }   

}

O código acima produz esta saída para mim:
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

Soluções alternativas:

Você tem poucas opções:

  1. Solução mais simples:não faça uma transação. Defina o connection.setAutoCommit(false); para connection.setAutoCommit(true); . Funciona porque o SQL com falha é simplesmente ignorado como uma instrução SQL com falha. Você pode falhar em instruções SQL o quanto quiser e o PostgreSQL não o impedirá.

  2. Permaneça em uma transação, mas quando você detectar que o primeiro SQL falhou, faça rollback/re-start ou commit/restart da transação. Em seguida, você pode continuar falhando em quantas consultas SQL nessa conexão de banco de dados desejar.

  3. Não capture e ignore a exceção que é lançada quando uma instrução SQL falha. Em seguida, o programa irá parar na consulta malformada.

  4. Em vez disso, obtenha o Oracle, o Oracle não lança uma exceção quando você falha em uma consulta em uma conexão dentro de uma transação e continua usando essa conexão.

Em defesa da decisão do PostgreSQL de fazer as coisas desta forma... Oracle foi deixando você mole no meio, deixando você fazer coisas idiotas e ignorando isso.