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


152

Estou vendo o seguinte rastreamento de pilha (truncado) no arquivo server.log do 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

A inspeção do arquivo de log do Postgres revela as seguintes instruções:

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

Estou usando o Infinispan enviado com o JBoss 7.1.1 Final, que é 5.1.2.Final.

Então é isso que eu acho que está acontecendo:

  • O Infinispan tenta executar a SELECT count(*)...instrução para ver se há algum registro no ISPN_MIXED_BINARY_TABLE_configCache;
  • O Postgres, por algum motivo, não gosta desta declaração.
  • O Infinispan ignora isso e avança com a CREATE TABLEdeclaração.
  • O Postgres vomita porque ainda pensa que é a mesma transação, que o Infinispan não conseguiu reverter, e essa transação é derivada da primeira SELECT count(*)...instrução.

O que esse erro significa e alguma idéia de como contorná-lo?


Só se você veio aqui, como eu, procurando pelo PSQLException: current transaction is aborted...( acima 25P02) e talvez também JPAou Hibernate. Finalmente, foi devido ao nosso (bom!) Uso de Logback alimentado com um toString()objeto DAO sobrecarregado que causou o erro e foi bem engolido (mas despercebido por mim): log.info( "bla bla: {}", obj )produzido bla bla: [FAILED toString()]. alterá-lo para log.info( "bla bla: {}", String.valueOf( obj )torná-lo seguro para nulos, mas não engoli-lo e, portanto, deixando a transação aberta com falha em uma consulta não relacionada.
Andreas Dietrich

Eu estava recebendo o mesmo tipo de erro. Eu tive que liberar a conexão antes do sql. O meu código era connection.commit ()
md. ariful ahsan 5/09/19

Respostas:


203

Eu recebi esse erro usando Java e postgresql fazendo uma inserção em uma tabela. Ilustrarei 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 para você obter esse erro é porque você inseriu uma transação e uma das suas Consultas SQL falhou, e você engoliu a falha e a ignorou. Mas isso não foi suficiente, então você usou a mesma conexão, usando a mesma transação para executar outra consulta. A exceção é lançada na segunda consulta formada corretamente, porque você está usando uma transação quebrada para realizar trabalho adicional. O Postgresql, por padrão, impede você de fazer isso.

Estou a usar: 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 do postgresql é: postgresql-9.2-1000.jdbc4.jar

Usando a versão java: Java 1.7

Aqui está a instrução create da 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 esteja em uma transação. Defina connection.setAutoCommit(false);como connection.setAutoCommit(true);. Funciona porque o SQL com falha é apenas ignorado como uma instrução sql com falha. Você pode falhar nas instruções sql o quanto quiser e o postgresql não irá impedi-lo.

  2. Continue sendo uma transação, mas quando detectar que o primeiro sql falhou, reverter / reiniciar ou confirmar / reiniciar a transação. Em seguida, você pode continuar falhando quantas consultas sql nessa conexão com o banco de dados desejar.

  3. Não pegue e ignore a exceção lançada quando uma instrução sql falha. Em seguida, o programa será interrompido na consulta incorreta.

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

Em defesa da decisão do postgresql de fazer as coisas desta maneira ... A Oracle estava deixando você mole no meio, deixando você fazer coisas idiotas e ignorando isso.


10
Lol @ Opção 4 ... Eu desenvolvi bastante no Oracle, e recentemente comecei a usar o Postgres ... é realmente irritante que o Postgres faça isso, e agora temos que reescrever uma grande parte do nosso programa. estão migrando do Oracle para o Postgres. Por que não existe uma opção como a primeira para fazê-lo se comportar como o Oracle, mas sem a confirmação automática ?
ADTC

2
Descobrimos, após alguns testes, que a Opção 2 é a mais próxima possível do comportamento do Oracle. Se você precisa emitir várias atualizações, e uma falha não deve parar actualizações subsequentes, basta ligar rollback()no Connectionquando um SQLExceptioné pego. [ De qualquer forma , percebi que isso está alinhado com a filosofia do PostgreSQL de forçar o usuário a deixar tudo explícito, enquanto a Oracle tem a filosofia de cuidar implicitamente de muitas coisas.]
ADTC

2
A opção 2 contém ramificação impossível or commit/restart the transaction. Como posso ver, não há como confirmar após a exceção. Quando tento cometer - PostgreSQL fazerrollback
turbanoff

1
Posso confirmar o problema levantado por @turbanoff. Isso também pode ser reproduzido diretamente com psql. (1) inicie uma transação, (2) emita algumas instruções válidas, (3) emita uma declaração inválida, (4) commit -> psql reverterá em vez de confirmar.
AlphaAa

1
postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl uma discussão interessante sobre este tópico. Se esse problema for desencadeado por uma violação de restrição, os desenvolvedores do PostgreSQL recomendam a verificação antecipada de um conflito (consulta antes da atualização / inserção) ou o uso savepointspara reverter para o ponto anterior à atualização / inserção. Consulte stackoverflow.com/a/28640557/14731 para obter um código de exemplo.
Gili

27

Verifique a saída antes da declaração que causou current transaction is aborted. Isso normalmente significa que o banco de dados lançou uma exceção que seu código ignorou e agora espera que as próximas consultas retornem alguns dados.

Portanto, agora você tem uma incompatibilidade de estado entre seu aplicativo, que considera as coisas boas e o banco de dados, que exige que você reverta e reinicie sua transação desde o início.

Você deve capturar todas as exceções e transações de reversão nesses casos.

Aqui está uma questão semelhante.


Isso é ótimo, exceto que nesse caso seria o Infinispan, uma biblioteca de terceiros, conversando com o Postgres, e não o meu código.
Jimidy

Bem, a situação continua a mesma - a transação deve ser revertida. Talvez verifique se há uma versão mais recente da biblioteca que você está usando ou aumente o problema no rastreador de erros. Se você encontrar exatamente o SQLque causou o problema, terá algum campo para eliminá-lo usando a extensibilidade do PostgreSQL.
Vyegorov 01/05

Parece que você confirmou minhas suspeitas - vou ver a fonte do Infinispan 5.1.2 agora.
197 Jimidy

Para ser justo, na classe TableManipulation, há uma tentativa de tentar executar a contagem de seleção (*) .... Talvez o driver do Postgres não esteja lançando uma das exceções esperadas. Vou conectar um depurador ao JBoss para tentar descobrir mais.
Jimidy

O código Infinispan em questão foi sugerido neste bug: issues.jboss.org/browse/… Anexei um depurador a ele em execução em uma instância ativa do JBoss 7.1.1 e o Postgres está lançando exceções nos lugares certos. Talvez sejam as instruções JdbcUtil.safeClose () que não estão funcionando bem. Vou levantá-lo com o Infinispan.
Jimidy

13

Eu acho que a melhor solução é usar java.sql.Savepoint.

Antes de executar a consulta que pode lançar o SQLException, use o método Connection.setSavepoint () e, se a exceção for lançada, você reverterá somente para esse ponto de salvamento, e não reverterá todas as transações.

Código de exemplo:

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

   }
}

Eu acidentalmente votei de alguma forma, apenas notei. Não foi intencional, não posso desfazer a menos que a resposta seja editada.
Cerberos

A maneira de salvar pontos é a solução real. Funciona para mim também no ambiente de PHP, Doctrine2 e Postgres (9.5). Obrigado
helvete

6

Houve algum trabalho realizado no driver JDBC do postgresql, relacionado a esse comportamento:
consulte https://github.com/pgjdbc/pgjdbc/pull/477

Agora é possível, definindo

gravação automática = sempre
na conexão (consulte https://jdbc.postgresql.org/documentation/head/connect.html ) para evitar o syndroma 'a transação atual foi abortada'.
A sobrecarga devido ao tratamento de um ponto de salvamento em torno da execução da instrução é mantida muito baixa (consulte o link acima para obter detalhes).


5

No Ruby on Rails PG, criei uma migração, migrei meu banco de dados, mas esqueci de reiniciar meu servidor de desenvolvimento. Eu reiniciei meu servidor e funcionou.


Esse foi o meu caso também. Achei que deveria ser algo estúpido, porque eu realmente não tentei fazer nada tão complicado.
Tashows 29/08/18

4

A razão para esse erro é que há outro banco de dados antes que a operação incorreta que leva à operação atual do banco de dados não possa ser realizada (eu uso a tradução do google para traduzir meu chinês para inglês)



2

Você precisa reverter. O driver do JDBC Postgres é muito ruim. Mas se você deseja manter sua transação e reverter esse erro, pode usar pontos de salvamento:

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

Leia mais aqui:

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


2

Eu tive o mesmo problema, mas percebi que há uma tabela com o mesmo nome no banco de dados. Depois de excluir, consegui importar o arquivo.


Esse era o meu problema, as tabelas para mim estavam em dois esquemas diferentes.
tomate

0

Esse é um comportamento muito estranho do PostgreSQL; ele não está "alinhado com a filosofia do PostgreSQL de forçar o usuário a tornar tudo explícito" - como a exceção foi capturada e ignorada explicitamente. Portanto, mesmo essa defesa não se sustenta. A Oracle, nesse caso, se comporta muito mais amigável e (quanto a mim) corretamente - deixa uma opção para o desenvolvedor.


0

Isso pode acontecer se você estiver sem espaço em disco no volume.


Sei que essa não é a causa mais comum, mas esse foi o caso em um servidor que foi solicitado a solucionar. Então, acho que isso deve ser listado como uma causa potencial.
gregb


0

Estou usando o JDBI com o Postgres e encontrei o mesmo problema, ou seja, após uma violação de alguma restrição de uma declaração de transação anterior, as instruções subsequentes falhariam (mas depois de esperar um pouco, digamos 20 a 30 segundos, o problema desaparece )

Após algumas pesquisas, descobri que o problema era fazer transações "manualmente" no meu JDBI, ou seja, cercava minhas declarações com BEGIN; ... COMMIT; e acaba por ser o culpado!

No JDBI v2, posso apenas adicionar a anotação @Transaction, e as instruções em @SqlQuery ou @SqlUpdate serão executadas como uma transação, e o problema acima mencionado não ocorrerá mais!


0

No meu caso, eu estava recebendo esse erro porque meu arquivo estava corrompido. Enquanto iterava os registros dos arquivos, estava me dando o mesmo erro.

Pode ser que no futuro ajude a alguém. Essa é a única razão para postar esta resposta.


0

Uso spring com @Transactionalanotação e pego a exceção e, por alguma exceção, tentarei novamente 3 vezes.

Para posgresql, quando há exceção, você não pode usar a mesma conexão para confirmar mais. Você deve reverter primeiro.

No meu caso, uso o DatasourceUtilspara obter a conexão atual e ligar connection.rollback()manualmente. E a chamada de método recrutar para tentar novamente.


0

Eu estava trabalhando com o jpa de inicialização por mola e corrigido implementando @EnableTransactionManagement

O arquivo anexado pode ajudá-lo.insira a descrição da imagem aqui


0

Eu estava trabalhando com o jpa de inicialização por mola e corrigido implementando @EnableTransactionManagement

O arquivo anexado pode ajudá-lo.


0

Tente isto COMMIT;

Eu corro isso no pgadmin4. Isso pode ajudar. Tem a ver com o comando anterior parar prematuramente


-1

Altere o nível de isolamento de leitura repetível para leitura confirmada.


-1

Defina conn.setAutoCommit (false) como conn.setAutoCommit (true)

Confirme as transações antes de iniciar uma nova.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.