【问题标题】:PSQLException: current transaction is aborted, commands ignored until end of transaction blockPSQLException:当前事务被中止,命令被忽略,直到事务块结束
【发布时间】:2012-05-11 02:23:36
【问题描述】:

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

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(*)... 语句中提取出来的。

这个错误是什么意思,知道如何解决它吗?

【问题讨论】:

  • 如果你像我一样来这里搜索上面的PSQLException: current transaction is aborted... (25P02) 或者JPAHibernate。最后,这是由于我们的(很好!)Logback 使用由 toString()-overloaded DAO 对象提供,导致错误并被很好地吞下(但我不小心没有注意到):log.info( "bla bla: {}", obj ) 产生 bla bla: [FAILED toString()]。将其更改为 log.info( "bla bla: {}", String.valueOf( obj ) 使其为空安全,但不会吞下它,从而使事务在不相关的查询上失败。
  • 我遇到了相同类型的错误。我必须在 sql 之前释放连接。我的代码是 connection.commit()
  • 我已经在这里回答了stackoverflow.com/a/65172183/3323007 并且有效!
  • 有两种方法可以解决这个问题。 1)运行回滚;这将使用当前选项卡对问题进行排序,2)打开一个新选项卡并运行相同的命令。尝试在查询运行中添加try catch。

标签: postgresql jboss infinispan


【解决方案1】:

我在使用 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 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 不会引发异常。

为了捍卫 PostgreSQL 以这种方式做事的决定……Oracle 让你在中间变得软弱,让你做愚蠢的事情并忽略它。

【讨论】:

  • Lol @ Option 4...我在Oracle中做了很多开发,最近开始使用Postgres... Postgres这样做真的很烦人,现在我们必须真正重写我们正在将大部分程序从 Oracle 移植到 Postgres。为什么没有像第一个这样的选项让它像 Oracle 但没有自动提交
  • 经过一些试验后发现,选项 2 是最接近 Oracle 行为的方法。如果您需要发布多个更新,并且一次失败不应停止后续更新,只需在捕获到SQLException 时在Connection 上调用rollback()。 [无论如何我意识到这符合 PostgreSQL 强制用户明确所有事情的理念,而 Oracle 的理念是隐式处理很多事情。]
  • 选项 2 包含不可能的分支 or commit/restart the transaction。正如我所看到的,在异常之后没有办法提交。当我尝试提交时 - PostgreSQL 执行 rollback
  • 我可以确认@turbanoff 提出的问题。这也可以直接用psql 复制。 (1) 启动事务,(2) 发出一些有效的语句,(3) 发出无效的语句,(4) 提交 --> psql 将回滚而不是提交。
  • postgresql.org/message-id/op.ur57x9ue33x80h%40insanity.lain.pl 这个话题的有趣讨论。如果这个问题是由违反约束触发的,PostgreSQL 开发人员建议提前检查冲突(在更新/插入之前查询)或使用savepoints 回滚到更新/插入之前的点。示例代码见stackoverflow.com/a/28640557/14731
【解决方案2】:

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

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

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

Here's a similar issue.

【讨论】:

  • 很好,除了在这种情况下,它会是 Infinispan,一个 3rd 方库,与 Postgres 对话,而不是我的代码。
  • 嗯,情况还是一样——事务必须回滚。也许检查您正在使用的库是否有更新版本,或者在他们的错误跟踪器中提出问题。如果您能找到导致该问题的确切 SQL,您将有一些字段可以使用 PostgreSQL 可扩展性来消除该问题。
  • 看来你已经证实了我的怀疑 - 我现在要查看 Infinispan 5.1.2 源代码。
  • 公平地说,在 TableManipulation 类中,围绕尝试运行 select count(*)... 有一个 try-catch。也许 Postgres 驱动程序没有抛出预期的异常之一。我会将调试器连接到 JBoss 以尝试了解更多信息。
  • 这个错误中建议了有问题的 Infinispan 代码:issues.jboss.org/browse/… 我已经附加了一个调试器,它在实时 JBoss 7.1.1 实例上运行,Postgres 在正确的地方抛出异常。也许是 JdbcUtil.safeClose() 语句没有发挥作用。我将用 Infinispan 提出它。
【解决方案3】:

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

在您执行可以throw 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) {}

   }
}

【讨论】:

  • 我不小心投了反对票,只是注意到了。不是故意的,除非编辑答案,否则我无法撤消。
  • 保存点方式是实际解决方案。在 PHP、Doctrine2 和 Postgres (9.5) 环境中也适用于我。谢谢
【解决方案4】:

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

现在可以通过设置

autosave=always
在连接中(请参阅https://jdbc.postgresql.org/documentation/head/connect.html)以避免“当前事务被中止”综合症。
由于在语句执行期间处理保存点而导致的开销保持非常低(请参阅链接详情见上)。

【讨论】:

  • IMO,这应该被接受这个问题的答案。此外,与“autosave=always”一起,建议设置“cleanupSavepoints=true”以避免用完共享缓冲区。
【解决方案5】:

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

【讨论】:

  • 这也是我的情况。认为这应该是愚蠢的,因为我并没有真正尝试做任何复杂的事情。
【解决方案6】:

这个错误的原因是之前有其他数据库错误操作导致当前数据库操作无法进行(我用google翻译我的中文翻译成英文)

【讨论】:

    【解决方案7】:

    试试这个COMMIT;

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

    【讨论】:

    • 为我解决了问题)
    【解决方案8】:

    您需要回滚。 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

    【讨论】:

      【解决方案9】:

      该问题已在 Infinispan 5.1.5.CR1 中修复:ISPN-2023

      【讨论】:

        【解决方案10】:

        我遇到了同样的问题,但后来意识到数据库中有一个同名的表。删除后我就可以导入文件了。

        【讨论】:

        • 这是我的问题,我的表跨越两个不同的模式。
        【解决方案11】:

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

        【讨论】:

        • 我意识到这不是最常见的原因,但在我被要求进行故障排除的服务器上就是这种情况。所以我认为这应该被列为潜在原因。
        【解决方案12】:

        对我来说,问题是没有安装驱动程序。我下载了驱动程序并粘贴到 ~/Library/Tableau/Driver(mac) 文件夹中,它工作正常。

        【讨论】:

          【解决方案13】:

          这是 PostgreSQL 非常奇怪的行为,它甚至不符合 PostgreSQL 强制用户明确所有内容的哲学——因为异常被明确地捕获和忽略。因此,即使这种辩护也不成立。在这种情况下,Oracle 的行为更加用户友好并且(就我而言)正确 - 它为开发人员留下了选择。

          【讨论】:

            【解决方案14】:

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

            我推荐了this

            【讨论】:

              【解决方案15】:

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

              经过一番研究,我发现问题在于我在 JDBI 中“手动”执行事务,即我用 BEGIN;...COMMIT; 包围了我的语句。原来是罪魁祸首!

              在JDBI v2中,我只需添加@Transaction注解,@SqlQuery或@SqlUpdate内的语句将作为事务执行,不再出现上述问题!

              【讨论】:

                【解决方案16】:

                在我的情况下,我收到此错误是因为我的文件已损坏。在迭代文件记录时,它给了我同样的错误。

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

                【讨论】:

                  【解决方案17】:

                  我使用带有@Transactional注解的spring,我捕获了异常,对于某些异常我会重试3次。

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

                  就我而言,我使用DatasourceUtils 获取当前连接并手动调用connection.rollback()。并调用recruive方法进行重试。

                  【讨论】:

                    【解决方案18】:

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

                    附件可以帮助你。

                    【讨论】:

                      【解决方案19】:

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

                      【讨论】:

                        【解决方案20】:

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

                        附件可以帮助你。

                        【讨论】:

                          猜你喜欢
                          • 2011-01-13
                          • 2013-08-04
                          • 2016-12-11
                          • 1970-01-01
                          • 2011-12-06
                          • 2013-10-25
                          • 1970-01-01
                          • 2014-07-04
                          • 1970-01-01
                          相关资源
                          最近更新 更多