PSQLException:当前事务被中止,命令被忽略,直到事务块结束
我在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
是否有任何logging; - Postgres,由于某种原因,不喜欢这种说法。
- Infinispan忽略了这一点,并用
CREATE TABLE
语句向前发展。 - Postgres barfs,因为它仍然认为它是同一个事务,Infinispan没有回滚,而且这个事务是从第一个
SELECT count(*)...
语句开始的。
这个错误是什么意思和任何想法如何解决它?
我得到这个错误使用Java和postgresql做一个表上的插入。 我将说明如何重现此错误:
org.postgresql.util.PSQLException: ERROR: current transaction is aborted, commands ignored until end of transaction block
概要:
你得到这个错误的原因是因为你input了一个事务,并且你的一个SQL查询失败,并且你吞下了那个失败并且忽略了它。 但是这还不够,那么你使用相同的连接,使用SAME TRANSACTION运行另一个查询。 第二个正确形成的查询会引发exception,因为您正在使用已损坏的事务来执行其他工作。 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语句来说明exception:
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
解决方法:
你有几个select:
-
最简单的解决scheme:不要在交易中。 设置
connection.setAutoCommit(false);
到connection.setAutoCommit(true);
。 它的工作原理是因为失败的SQL被忽略为失败的sql语句。 欢迎您不必担心sql语句,postgresql不会阻止您。 -
保持在事务中,但是当您检测到第一个sql失败时,可以回滚/重新启动或提交/重新启动事务。 然后,您可以继续在该数据库连接上尽可能多的sql查询失败。
-
不要忽略和忽略sql语句失败时引发的exception。 然后该程序将停止对格式不正确的查询。
-
换而言之,Oracle在事务中的连接上的查询失败并且继续使用该连接时不会引发exception。
为了防止postgresql以这种方式做事情的决定……甲骨文让你在中间变得柔软,让你做愚蠢的事情,并忽略它。
在导致current transaction is aborted
的语句current transaction is aborted
之前检查输出。 这通常意味着数据库抛出了一个exception,您的代码已经忽略,现在期待下一个查询返回一些数据。
所以,现在你的应用程序和数据库之间的状态不匹配,需要你从一开始就回滚并重新启动你的事务。
在这种情况下,您应该捕获所有exception和回滚事务。
这是一个类似的问题。
我认为最好的解决scheme是使用java.sql.Savepoint。
在执行查询之前,可以抛出SQLException使用方法Connection.setSavepoint(),如果抛出exception,则只会回滚到此保存点而不回滚所有事务。
示例代码:
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) {} } }
在Ruby on Rails PG中,我创build了一个迁移,迁移了我的数据库,但忘了重启我的开发服务器。 我重新启动我的服务器,它的工作。
Infinispan 5.1.5.CR1: ISPN-2023已经解决了这个问题
你需要回滚。 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
之所以出现这个错误,是因为有其他数据库在错误的操作之前导致当前的数据库操作无法进行(我用谷歌翻译把我的中文翻译成英文)
这是PostgreSQL的非常奇怪的行为,它甚至不符合PostgreSQL强制用户将所有内容明确化的理念 – 因为exception被明确地捕获和忽略。 所以即使这个防守也不成立。 在这种情况下,甲骨文的行为更加方便用户(正如我一样) – 这给开发者留下了一个select。
如果磁盘空间不足,可能会发生这种情况。
我只是遇到了同样的错误。 我能够通过在本地PostgreSQL中启用log_statement和log_min_error_statement来找出根本原因。
我提到这一点
我使用JDBI与Postgres,并遇到了同样的问题,即违反了前一个交易声明约束,后续的声明将失败(但是等待一段时间后,说20-30秒,问题就消失了)。
经过一番研究,我发现问题是我在做我的JDBI“手动”事务,即我用BEGIN包围了我的语句; … COMMIT; 事实certificate是罪魁祸首!
在JDBI v2中,我只需添加@Transaction注释,@SqlQuery或@SqlUpdate中的语句将作为一个事务来执行,而上述问题不会再发生了!
将隔离级别从可重复读取更改为已提交。