PSQLException:当前事务被中止,命令被忽略直到事务块结束

时间:2012-05-01 15:11:22

标签: postgresql jboss infinispan

我在JBoss 7.1.1 Final的server.log文件中看到以下(截断的)stacktrace:

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

检查Postgres日志文件会显示以下语句:

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

我正在使用JBoss 7.1.1 Final附带的Infinispan,它是5.1.2.Final。

所以这就是我的想法:

  • Infinispan尝试运行SELECT count(*)...语句,以查看ISPN_MIXED_BINARY_TABLE_configCache中是否有任何记录;
  • Postgres出于某种原因,不喜欢这句话。
  • Infinispan忽略了这一点并继续使用CREATE TABLE声明。
  • Postgres barfs因为它仍然认为它是同一个事务,Infinispan无法回滚,而且这个事务是从第一个SELECT count(*)...声明中获得的。

这个错误是什么意思,任何想法如何解决它?

20 个答案:

答案 0 :(得分:163)

我使用Java和postgresql在表上执行插入时出现此错误。我将说明如何重现此错误:

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

<强>要点:

您收到此错误的原因是您输入了一个事务并且其中一个SQL查询失败,并且您吞并了该失败并忽略了它。但这还不够,那么你使用相同的连接,使用SAME TRANSACTION运行另一个查询。由于您使用损坏的事务执行其他工作,因此会在第二个正确形成的查询上抛出异常。 Postgresql默认阻止你这样做。

我正在使用: 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".

我的postgresql驱动程序是: postgresql-9.2-1000.jdbc4.jar

使用java版本: Java 1.7

这是用于说明异常的表create语句:

CREATE TABLE moobar
(
    myval   INT
);

Java程序导致错误:

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

}

上面的代码为我生成了这个输出:

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

<强>解决方法:

您有几个选择:

  1. 最简单的解决方案:不要在交易中。将connection.setAutoCommit(false);设置为connection.setAutoCommit(true);。它的工作原理是因为失败的SQL只是作为失败的sql语句而被忽略。欢迎您使用所有想要的SQL语句失败,postgresql也不会阻止您。

  2. 保持在事务中,但是当您检测到第一个sql失败时,要么回滚/重新启动,要么提交/重新启动事务。然后,您可以根据需要继续在该数据库连接上执行尽可能多的SQL查询失败。

  3. 不要捕获并忽略sql语句失败时抛出的异常。然后程序将停止格式错误的查询。

  4. 改为使用Oracle,当您对事务中的连接进行查询失败并继续使用该连接时,Oracle不会抛出异常。

  5. 为了保护postgresql决定以这种方式做事...... Oracle 让你在中间软,让你做蠢事并忽视它。

答案 1 :(得分:21)

检查输出之前导致current transaction is aborted的语句。这通常意味着数据库抛出了您的代码已忽略的异常,现在希望下一个查询返回一些数据。

因此,现在您的应用程序和数据库之间存在状态不匹配,该应用程序认为一切正常,数据库需要您从头开始回滚并重新启动事务。

在这种情况下,您应该捕获所有异常和回滚事务。

Here's a similar issue.

答案 2 :(得分:8)

我认为最好的解决方案是使用java.sql.Savepoint。

在执行查询之前,可以抛出SQLException,使用方法Connection.setSavepoint(),如果异常将抛出,则只回滚到此保存点而不回滚所有事务。

示例代码:

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

   }
}

答案 3 :(得分:5)

在Ruby on Rails PG中,我创建了一个迁移,迁移了我的数据库,但忘了重新启动我的开发服务器。我重新启动了我的服务器并且运行良好。

答案 4 :(得分:3)

这个错误的原因是,在错误的操作之前还有其他数据库导致当前数据库操作无法执行(我使用谷歌翻译将我的中文翻译成英文)

答案 5 :(得分:2)

此问题已在Infinispan 5.1.5.CR1:ISPN-2023

中修复

答案 6 :(得分:2)

在postgresql JDBC Driver上已经完成了一些与此行为相关的工作:
https://github.com/pgjdbc/pgjdbc/pull/477

现在可以通过在连接中设置

autosave=always
(参见https://jdbc.postgresql.org/documentation/head/connect.html)来避免“当前交易中止”的综合症。
由于处理语句执行周围的保存点保持很低(详见上面的链接)。

答案 7 :(得分:2)

您需要回滚。 JDBC Postgres驱动程序非常糟糕。但是,如果您想保留您的事务,并且只是回滚该错误,则可以使用保存点:

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

在这里阅读更多内容:

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

答案 8 :(得分:1)

我有同样的问题但后来意识到数据库中有一个同名的表。删除后我能够导入文件。

答案 9 :(得分:0)

如果卷上的磁盘空间不足,就会发生这种情况。

答案 10 :(得分:0)

我刚遇到同样的错误。通过在我的本地PostgreSQL中启用log_statementlog_min_error_statement,我能够找出根本原因。

我提到了this

答案 11 :(得分:0)

我正在使用Postgres的JDBI,并遇到同样的问题,即在上一次事务的语句中违反某些约束后,后续语句将失败(但在我等待一段时间后,比如20-30秒,问题消失了。)

经过一番研究,我发现问题是我在JDBI中“手动”进行交易,即我用BEGIN包围我的语句; ... COMMIT;结果证明是罪魁祸首!

在JDBI v2中,我可以添加@Transaction注释,@ SqlQuery或@SqlUpdate中的语句将作为事务执行,上述问题不再发生!

答案 12 :(得分:0)

这是PostgreSQL非常奇怪的行为,它甚至没有“强制用户使一切都明确的PostgreSQL理念” - 因为异常被捕获并被明确忽略。所以即使这种防守也不成立。在这种情况下,Oracle表现得更加用户友好,并且(对我而言)正确 - 它为开发人员留下了选择。

答案 13 :(得分:0)

将conn.setAutoCommit(false)设置为conn.setAutoCommit(true)

在启动新交易之前先提交交易。

答案 14 :(得分:0)

在我的情况下,由于文件已损坏,我遇到了此错误。在迭代文件记录时,它给了我同样的错误。

将来可能会帮助任何人。这是发布此答案的唯一原因。

答案 15 :(得分:0)

我使用带有@Transactional批注的spring,并且捕获到异常,对于某些异常,我将重试3次。

对于posgresql,当出现异常时,您不能再使用同一Connection进行提交。您必须先回滚。

对于我来说,我使用DatasourceUtils获得当前连接并手动调用connection.rollback()。然后调用该方法可重试。

答案 16 :(得分:0)

我正在使用spring boot jpa并通过实施进行修复 @EnableTransactionManagement

附加的文件可能会对您有所帮助。enter image description here

答案 17 :(得分:0)

我正在使用spring boot jpa并通过实施进行修复 @EnableTransactionManagement

附加的文件可能会对您有所帮助。

答案 18 :(得分:0)

尝试一下COMMIT;

我在pgadmin4中运行它。这可能会有所帮助。 与上一个命令过早停止有关

答案 19 :(得分:-1)

将隔离级别从可重复读取更改为读取已提交。