PSQLException: текущая транзакция прерывается, команды игнорируются до конца блока транзакции

Я вижу следующую (усеченную) stacktrace в файле server.log 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

Проверка файла журнала 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

Я использую Infinispan, поставляемый с JBoss 7.1.1 Final, который является 5.1.2.Final.

Так вот что я думаю, что происходит:

  • Infinispan пытается запустить оператор SELECT count(*)..., чтобы увидеть, есть ли записи в ISPN_MIXED_BINARY_TABLE_configCache;
  • Postgres по какой-то причине не любит этот оператор.
  • Infinispan игнорирует это и продолжает работу с инструкцией CREATE TABLE.
  • Postgres barfs, потому что он все еще считает, что это та же транзакция, которую Infinispan не удалось отменить, и эта транзакция выведена из первого оператора SELECT count(*)....

Что означает эта ошибка и любая идея, как ее обойти?

Ответ 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

Обходные:

У вас есть несколько вариантов:

  • Простейшее решение: не выполняйте транзакции. Установите для параметра connection.setAutoCommit(false); значение connection.setAutoCommit(true);. Это работает, потому что неудавшийся SQL просто игнорируется как неудачный SQL-запрос. Вы можете отказаться от SQL-запросов, которые вы хотите, и postgresql не остановит вас.

  • Оставайтесь в транзакции, но когда вы обнаруживаете, что первый sql не сработал, либо откат/повторный запуск, либо фиксация/перезапуск транзакции. Затем вы можете продолжить сбой по количеству запросов sql в этом соединении с базой данных, как вы хотите.

  • Не улавливайте и игнорируйте Исключение, которое вызывается при сбое SQL-запроса. Затем программа остановится на неверном запросе.

  • Получите Oracle вместо этого, Oracle не генерирует исключение, если вы не выполняете запрос по соединению в транзакции и продолжаете использовать это соединение.

В защиту решения postgresql сделать так, что... Oracle сделал вас мягким в середине, позволяя вам делать глупые вещи и игнорировать его.

Ответ 2

Проверьте вывод перед оператором, вызвавшим current transaction is aborted. Это обычно означает, что база данных создала исключение, которое ваш код проигнорировал и теперь ожидает, что следующие запросы возвратят некоторые данные.

Итак, теперь у вас есть несоответствие состояния между вашим приложением, которое считает, что все в порядке, и базы данных, что требует от вас отката и перезапуска транзакции с самого начала.

В таких случаях вы должны поймать все исключения и транзакции отката.

Здесь аналогичная проблема.

Ответ 3

Я думаю, что лучшим решением является использование 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) {}

   }
}

Ответ 4

В Ruby on Rails PG я создал миграцию, перенести мою БД, но забыл перезагрузить мой сервер разработки. Я перезапустил свой сервер, и он сработал.

Ответ 5

Проблема была исправлена ​​в Infinispan 5.1.5.CR1: ISPN-2023

Ответ 6

Вам нужно откат. Драйвер 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

Ответ 7

Причиной этой ошибки является то, что есть другая база данных до того, как неправильная операция привела к текущей операции с базой данных, не может быть выполнена (я использую перевод Google для перевода моего китайского языка на английский)

Ответ 8

Это очень странное поведение PostgreSQL, оно даже не "согласуется с философией PostgreSQL заставляя пользователя делать все явным", поскольку исключение было поймано и проигнорировано явно. Так что даже эта защита не выполняется. Oracle в этом случае ведет себя намного удобнее и (как для меня) правильно - он оставляет выбор разработчику.

Ответ 9

Это может произойти, если вы не используете дисковое пространство на томе.

Ответ 10

Я просто сталкиваюсь с той же ошибкой. Я смог выяснить основную причину, разрешив log_statement и log_min_error_statement в моем локальном PostgreSQL.

Я ссылался на

Ответ 11

Я использую JDBI с Postgres и столкнулся с одной и той же проблемой, то есть после нарушения какого-либо ограничения из инструкции предыдущей транзакции последующие операторы будут терпеть неудачу (но после того, как я подожду какое-то время, скажем, 20-30 секунд, проблема уходит).

После некоторых исследований я обнаружил, что проблема заключалась в том, что я делал транзакцию "вручную" в своем JDBI, то есть я окружал свои высказывания BEGIN;... COMMIT; и он оказывается виновником!

В JDBI v2 я могу просто добавить аннотацию @Transaction, а операторы в @SqlQuery или @SqlUpdate будут выполняться как транзакция, и вышеупомянутая проблема больше не повторится!

Ответ 12

Измените уровень изоляции от повторяемого чтения до чтения.