Меню

Error ошибка текущая транзакция прервана команды до конца блока транзакции игнорируются postgresql

I got this error using Java and PostgreSQL doing an insert on a table. I will illustrate how you can reproduce this error:

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

Summary:

The reason you get this error is because you have entered a transaction and one of your SQL Queries failed, and you gobbled up that failure and ignored it. But that wasn’t enough, THEN you used that same connection, using the SAME TRANSACTION to run another query. The exception gets thrown on the second, correctly formed query because you are using a broken transaction to do additional work. PostgreSQL by default stops you from doing this.

I’m using: 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".

My PostgreSQL driver is: postgresql-9.2-1000.jdbc4.jar

Using Java version: Java 1.7

Here is the table create statement to illustrate the Exception:

CREATE TABLE moobar
(
    myval   INT
);

Java program causes the error:

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

}

The above code produces this output for me:

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

Workarounds:

You have a few options:

  1. Simplest solution: Don’t be in a transaction. Set the connection.setAutoCommit(false); to connection.setAutoCommit(true);. It works because then the failed SQL is just ignored as a failed SQL statement. You are welcome to fail SQL statements all you want and PostgreSQL won’t stop you.

  2. Stay being in a transaction, but when you detect that the first SQL has failed, either rollback/re-start or commit/restart the transaction. Then you can continue failing as many SQL queries on that database connection as you want.

  3. Don’t catch and ignore the Exception that is thrown when a SQL statement fails. Then the program will stop on the malformed query.

  4. Get Oracle instead, Oracle doesn’t throw an exception when you fail a query on a connection within a transaction and continue using that connection.

In defense of PostgreSQL’s decision to do things this way… Oracle was making you soft in the middle letting you do dumb stuff and overlooking it.

I got this error using Java and PostgreSQL doing an insert on a table. I will illustrate how you can reproduce this error:

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

Summary:

The reason you get this error is because you have entered a transaction and one of your SQL Queries failed, and you gobbled up that failure and ignored it. But that wasn’t enough, THEN you used that same connection, using the SAME TRANSACTION to run another query. The exception gets thrown on the second, correctly formed query because you are using a broken transaction to do additional work. PostgreSQL by default stops you from doing this.

I’m using: 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".

My PostgreSQL driver is: postgresql-9.2-1000.jdbc4.jar

Using Java version: Java 1.7

Here is the table create statement to illustrate the Exception:

CREATE TABLE moobar
(
    myval   INT
);

Java program causes the error:

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

}

The above code produces this output for me:

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

Workarounds:

You have a few options:

  1. Simplest solution: Don’t be in a transaction. Set the connection.setAutoCommit(false); to connection.setAutoCommit(true);. It works because then the failed SQL is just ignored as a failed SQL statement. You are welcome to fail SQL statements all you want and PostgreSQL won’t stop you.

  2. Stay being in a transaction, but when you detect that the first SQL has failed, either rollback/re-start or commit/restart the transaction. Then you can continue failing as many SQL queries on that database connection as you want.

  3. Don’t catch and ignore the Exception that is thrown when a SQL statement fails. Then the program will stop on the malformed query.

  4. Get Oracle instead, Oracle doesn’t throw an exception when you fail a query on a connection within a transaction and continue using that connection.

In defense of PostgreSQL’s decision to do things this way… Oracle was making you soft in the middle letting you do dumb stuff and overlooking it.

I got this error using Java and PostgreSQL doing an insert on a table. I will illustrate how you can reproduce this error:

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

Summary:

The reason you get this error is because you have entered a transaction and one of your SQL Queries failed, and you gobbled up that failure and ignored it. But that wasn’t enough, THEN you used that same connection, using the SAME TRANSACTION to run another query. The exception gets thrown on the second, correctly formed query because you are using a broken transaction to do additional work. PostgreSQL by default stops you from doing this.

I’m using: 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".

My PostgreSQL driver is: postgresql-9.2-1000.jdbc4.jar

Using Java version: Java 1.7

Here is the table create statement to illustrate the Exception:

CREATE TABLE moobar
(
    myval   INT
);

Java program causes the error:

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

}

The above code produces this output for me:

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

Workarounds:

You have a few options:

  1. Simplest solution: Don’t be in a transaction. Set the connection.setAutoCommit(false); to connection.setAutoCommit(true);. It works because then the failed SQL is just ignored as a failed SQL statement. You are welcome to fail SQL statements all you want and PostgreSQL won’t stop you.

  2. Stay being in a transaction, but when you detect that the first SQL has failed, either rollback/re-start or commit/restart the transaction. Then you can continue failing as many SQL queries on that database connection as you want.

  3. Don’t catch and ignore the Exception that is thrown when a SQL statement fails. Then the program will stop on the malformed query.

  4. Get Oracle instead, Oracle doesn’t throw an exception when you fail a query on a connection within a transaction and continue using that connection.

In defense of PostgreSQL’s decision to do things this way… Oracle was making you soft in the middle letting you do dumb stuff and overlooking it.

Содержание

  1. Молчание Ruby-эксепшенов: транзакционный Rails/PostgreSQL триллер
  2. Транзакционные блокировки спешат на помощь
  3. Не так быстро…
  4. Идеальный шторм
  5. Альтернатива транзакционным блокировкам в PostgreSQL
  6. Но что делать с конкурентной вставкой одинаковых записей?
  7. Предотвращаем катастрофу в будущем
  8. Итоги
  9. Что почитать
  10. Postgresql error current transaction is aborted
  11. Environment
  12. Resolution
  13. PSQLException: текущая транзакция прервана, команды игнорируются до конца блока транзакции
  14. 19 ответы

Молчание Ruby-эксепшенов: транзакционный Rails/PostgreSQL триллер

Это история о том, почему вы никогда не должны замалчивать ошибки, когда вы внутри транзакции в базе данных. Узнайте, о том как правильно использовать транзакции и что делать, когда их использовать — не вариант. Спойлер: речь пойдёт об advisory locks в PostgreSQL!

Я работал над проектом, в котором пользователи могут импортировать большое количество тяжёлых сущностей (назовём их товарами — products) из внешнего сервиса в наше приложение. К каждому товару при этом загружается ещё больше разнообразных связанных с ним данных с внешних API. Нередка ситуация, когда пользователю нужно загрузить сотни товаров вместе со всеми-всеми зависимостями, в итоге импорт одного товара занимает ощутимое время (30-60 секунд), а весь процесс может порядочно так затянуться. Пользователю может надоесть ждать результата и у него есть право нажать кнопку «Отмена» в любой момент и приложение должно быть полезным с тем количеством товаров, которые удалось загрузить к этому моменту.

«Прерываемый импорт» реализован так: в начале для каждого товара создаётся временная запись-задача в табличке в БД. Для каждого товара запускается фоновая задача импорта, которая скачивала товар, сохраняла в базу вместе со всеми зависимостями (всё делает в общем) и уже в самом конце удаляет свою запись-задачу. Если к моменту, когда фоновая задача запустится, записи в базе не будет — задача просто тихо завершается. Таким образом, для отмены импорта достаточно просто удалить все задачи и всё.

Неважно, был ли импорт отменён пользователем или полностью завершился сам — в любом случае отсутствие задач означает, что всё закончилось и пользователь может начинать пользоваться приложением.

Дизайн прост и надёжен, но нашёлся в нём один маленький баг. Типовой багрепорт о нём звучал так: «После отмены импорта пользователю показывается список его товаров. Однако, если обновить страницу, то список товаров дополняется несколькими записями». Причина такого поведения проста — когда пользователь нажимал кнопку «Отмена», то его сразу же перебрасывало на список всех товаров. Но в это время уже начавшиеся импорты отдельных товаров ещё «добегают».

Это, конечно, мелочь, но пользователей порядком озадачивало, поэтому неплохо было бы исправить. У меня было два пути: как-то определить и «убить» уже запущенные задачи или при нажатии кнопки отмены подождать, пока они завершатся и «умрут своей смертью», прежде чем перекидывать пользователя дальше. Я выбрал второй путь — ждать.

Транзакционные блокировки спешат на помощь

Для всех, кто работает с (реляционными) базами данных, ответ очевиден: используйте транзакции!

При этом важно помнить, что в большинстве РСУБД записи, обновляемые внутри транзакции, будут заблокированы и недоступны для изменения другими процессами до тех пор, пока данная транзакция не завершится. Так же будут заблокированы и записи, отобранные с помощью SELECT FOR UPDATE .

Точно наш случай! Я обернул задачи импорта отдельных товаров в транзакцию и заблокировал запись-задачу в самом начале:

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

Просто и элегантно! Я прогнал тесты, проверил импорт локально и на стейджинге и задеплоил «в бой».

Не так быстро…

Удовлетворённый своей работой, я был весьма удивлён, обнаружив вскоре багрепорты и тонны ошибок в логах. Многие товары не импортировались вообще. В некоторых случаях только один-единственный товар мог остаться после завершения всего импорта.

Ошибки в логах тоже не воодушевляли: PG::InFailedSqlTransaction с бэктрейсом, ведущим в код, выполнявший невинные SELECT ы. Да что происходит вообще?

После целого дня изнурительной отладки, я выявил три главных причины проблем:

  1. Конкурентная вставка конфликтующих записей в базу данных.
  2. Автоматическая отмена транзакций в PostgreSQL после ошибок.
  3. Замалчивание проблем (Ruby exceptions) в коде приложения.

Проблема первая: Конкурентная вставка конфликтующих записей

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

Для нахождения и переиспользования одинаковых зависимостей в коде приложения есть проверки, но теперь, когда мы используем транзакции, эти проверки стали бесполезны: если транзакция А создала зависимую запись, но ещё не завершилась, то транзакция Б не сможет узнать о её существовании и попытается создать дублирующую запись.

Проблема вторая: Автоматическая отмена транзакций в PostgreSQL после ошибок

Мы, конечно же, предотвратили создание дублирующихся задач на уровне базы данных с помощью следующего DDL:

Если ещё идущая транзакция A вставила новую запись и параллельно с ней транзакция Б пытается вставить запись с такими же значениями полей user_id и characteristics — транзакция Б получит ошибку:

Но есть одна особенность, про которую нельзя забывать — транзакция Б после обнаружения ошибки будет автоматически отменена и вся проделанная в ней работа пойдёт насмарку. Однако, эта транзакция по прежнему открыта в «ошибочном» состоянии, но при любой попытке выполнить любой, даже самый безобидный запрос в ответ будут возвращаться лишь ошибки:

Ну и совсем излишне говорить, что всё, что было введено в базу в этой транзакции, сохранено уже не будет:

Проблема третья: Замалчивание проблем

К этому моменту уже стало ясно, что простое добавление транзакций к приложению его сломало. Выбора не было: пришлось погружаться в код импорта. В коде мне довольно часто стали попадаться на глаза следующие паттерны:

Автор кода тут как бы говорит нам: «Мы попытались, у нас не получилось, но ничего страшного, продолжаем без этого». И хотя причины такого выбора могут быть вполне объяснимы (не всё можно обработать на уровне приложения), именно это делает любую логику, основанную на транзакциях, невозможной: «выкинутый» эксепшен не сможет всплыть наверх, к блоку transaction , и не сможет вызвать корректный откат транзакции (ActiveRecord ловит все ошибки в этом блоке, откатывает транзакцию и кидает их снова).

Идеальный шторм

И вот как все эти три фактора сошлись, чтобы создать идеальный шторм баг:

  • Приложение в транзакции пытается вставить конфликтующую запись в базу данных и при этом вызывает ошибку «duplicate key» из PostgreSQL. Однако, эта ошибка не вызывает отката транзакции в приложении, так как она «замалчивается» внутри одной из частей приложения.
  • Транзакция становится недействительной, но приложение про это не знает и продолжает свою работу. При любой попытке обратиться к БД приложение снова получает ошибку, на этот раз «current transaction is aborted», но и эта ошибка может быть «выкинута»…
  • Вы наверное уже поняли — что-то в приложении продолжает ломаться, но никто не узнает про это до тех пор, пока выполнение не дойдёт до первого места, где нет чересчур жадного rescue и где ошибка может в конце концов всплыть, быть выведена в лог, зарегистрирована в трекере ошибок — что угодно. Но это место будет уже очень далеко от того места, которое стало первопричиной ошибки, и лишь одно это превратит отладку в кошмар.

Альтернатива транзакционным блокировкам в PostgreSQL

Охота за rescue в коде приложения и переписывание всей логики импорта — не вариант. Долго. Мне нужно было быстрое решение и у постгреса оно нашлось! У него есть встроенное решение для блокировок, альтернативное блокировке записей в транзакциях, встречайте — сессионные рекомендательные блокировки (session-level advisory locks). Я использовал их следующим образом:

Во-первых, сначала я убрал оборачивающую транзакцию. В любом случае, производить взаимодействия с внешними API (или любые другие «сайд-эффекты») из кода приложения при открытой транзакции — плохая идея, потому что при даже если откатить транзакцию вместе со всеми изменения в нашей базе данных — изменения во внешних системах останутся, а приложение в целом может оказаться в странном и нежелательном состоянии. Гем isolator может помочь вам убедиться в том, что сайд-эффекты как следует изолированы от транзакций.

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

Разделяемые блокировки на один и тот же ключ могут браться одновременно любым количеством сессий.

Операция отмены импорта при этом удаляет все записи-задачи из базы данных и пытается взять исключительную (exclusive) блокировку на тот же ключ. При этом ей придётся подождать, пока все разделяемые блокировки будут освобождены:

И это всё! Теперь «отмена» будет ждать, пока все уже «бегущие» импорты отдельных товаров завершатся.

Более того, теперь, когда мы не связаны транзакцией, мы можем использовать маленький хак, чтобы ограничить время ожидания отмены импорта (на случай, если какой-то импорт «залипнет»), потому что нехорошо надолго блокировать поток веб-сервера (да и заставлять пользователя ждать):

Ловить ошибку снаружи блока transaction безопасно, поскольку ActiveRecord уже откатит транзакцию.

Но что делать с конкурентной вставкой одинаковых записей?

К сожалению, я не знаю решения, которое бы хорошо работало при конкурентных вставках. Есть следующие подходы, но они все будут блокировать параллельные вставки до тех пор, пока первая из транзакций не завершится:

  • INSERT … ON CONFLICT UPDATE (доступно начиная с PostgreSQL 9.5) во второй транзакции заблокируется до завершения первой и потом вернёт запись, которая была вставлена первой транзакцией.
  • Заблокировать какую-то общую запись в транзакции перед тем, как прогонять валидации на вставку новой записи. Здесь мы будем ждать до тех пор, пока вставленная в другой транзакции запись не станет видна и валидации не смогут полноценно отработать.
  • Взять какую-нибудь общую рекомендательную блокировку — эффект тот же, что и для блокирования общей записи.

Ну а если вы не боитесь работать с ошибками уровня базы, можно просто ловить ошибку уникальности:

Только убедитесь, что данный код уже не обёрнут в транзакцию.

Ограничения UNIQUE и EXCLUDE блокируют потенциальные конфликты, не позволяя им быть записанным в одно и то же время. Например, если у вас есть ограничение уникальности на целочисленную колонку и одна транзакция вставляет строку со значением 5, то другие транзакции, которые тоже пытаются вставить 5, будут заблокированы, но транзакции, которые пытаются вставить 6 или 4 сразу выполнятся успешно, без блокировки. Поскольку минимальный фактический уровень изоляции транзакций в PostgreSQL — это READ COMMITED , то транзакция не вправе видеть незафиксированные изменения от других транзакций. Поэтому INSERT с конфликтующим значением не может быть принят или отвергнут до тех пор, пока первая транзакция не зафиксирует свои изменения (тогда вторая получит ошибку уникальности) или не откатится (тогда вставка во второй транзакции пройдёт успешно). Прочитайте об этом подробнее в статье от автора ограничений EXCLUDE.

Предотвращаем катастрофу в будущем

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

Для этого все ваши операции можно обернуть в небольшой вспомогательный модуль, который проверит, не открыта ли транзакция перед запуском кода обёрнутой операции (здесь предполагается, что у всех ваших операций одинаковый интерфейс — метод call ).

Теперь если кто-то попытается обернуть опасный сервис в транзакцию, то он сразу получит ошибку (если, конечно, не будет её «замалчивать»).

Итоги

Главный урок, которые следует вынести: будьте осторожны с исключениями. Не обрабатывайте все подряд, ловите только те исключения, которые вы знаете, как обрабатывать и позвольте остальным дойти до логов. Никогда не замалчивайте исключения (только если вы не 100% уверены, зачем вы это делаете). Чем раньше ошибка будет замечена — тем проще будет отладка.

И не перемудрите с транзакциями в БД. Это не панацея. Используйте наши гемы isolator и after_commit_everywhere — они помогут вашим транзакциям стать полностью дуракоустойчивыми.

Что почитать

Exceptional Ruby от Avdi Grimm. Эта небольшая книга научит вас правильно работать с существующими исключениями в Ruby и расскажет, как правильно спроектировать систему исключений для вашего приложения.

Using Atomic Transactions to Power an Idempotent API от @Brandur. В его блоге много полезных статей про надёжность приложений, Ruby и PostgreSQL.

Источник

Postgresql error current transaction is aborted

When attempting to connect to or refresh a PostgreSQL data source on Tableau Cloud or Tableau Server, or when dragging any measure or dimension to the columns/Rows shelf after the connection is made, the following error may occur:

An error occurred while communicating with PostgreSQL
Bad Connection: Tableau could not connect to the data source
ERROR: current transaction is aborted, commands ignored until end of transaction block; Error while executing the query

Environment

  • Tableau Cloud
  • Tableau Server
  • Tableau Desktop
  • PostgreSQL Database 12.1

Resolution

1. Workarounds for scenario 1: When attempting to connect to or refresh a PostgreSQL data source on Tableau Cloud (to track the status of this issue, see Issue ID 947669 on the Known Issues page). This has been resolved with the release of the PostgreSQL JDBC driver to Tableau Cloud.

2. Workaround for scenario 2: when dragging any measure or dimension to the columns/Rows shelf after the connection to PostgreSQL is made.

  • Uninstall the current version of the PostgreSQL driver installed on the machine.
  • Install the latest version of PostgreSQL driver, version 12.1. Note: the latest Postgres driver can be found here: https://www.postgresql.org/ftp/odbc/versions/msi/

For Tableau Server:

Upgrade to Tableau Server 2020.4 or later, A JDBC driver for PostgreSQL that supports PostgreSQL 12 is installed and used.

Источник

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

Я вижу следующую (усеченную) трассировку стека в файле server.log JBoss 7.1.1 Final:

Проверка файла журнала Postgres показывает следующие утверждения:

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

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

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

Что означает эта ошибка и есть идеи, как ее обойти?

задан 01 мая ’12, 16:05

Просто если бы вы пришли сюда, как я, в поисках вышеперечисленного PSQLException: current transaction is aborted. ( 25P02 ) а может быть и JPA or Hibernate . Наконец, благодаря нашему (приятному!) Логбэк использование, питаемое toString() -перегруженный объект DAO, вызвавший ошибку и красиво проглоченный (но случайно не замеченный мной): log.info( «bla bla: <>«, obj ) произведенный bla bla: [FAILED toString()] . изменить его на log.info( «bla bla: <>«, String.valueOf( obj ) сделал его нулевым, но не проглотил его и, таким образом, оставил транзакцию открытой с ошибкой по несвязанному запросу. — Andreas Covidiot

Я получал тот же тип ошибки. Мне пришлось разорвать соединение до того, как sql. Мой код был connection.commit() — md. ariful ahsan

Есть 2 способа исправить это. 1) запустить ОТКАТ; это решит проблему с текущей вкладкой, 2) откройте новую вкладку и выполните ту же команду. Попробуйте добавить try catch в запущенный запрос. — althaf a s

19 ответы

Я получил эту ошибку, используя Java и PostgreSQL, выполняющие вставку в таблицу. Я проиллюстрирую, как вы можете воспроизвести эту ошибку:

Резюме:

Причина, по которой вы получаете эту ошибку, заключается в том, что вы ввели транзакцию, и один из ваших SQL-запросов не удался, и вы проглотили этот сбой и проигнорировали его. Но этого было недостаточно, ТОГДА вы использовали то же самое соединение, используя ТУ ЖЕ ТРАНЗАКЦИЮ для запуска другого запроса. Исключение возникает при втором правильно сформированном запросе, потому что вы используете неработающую транзакцию для выполнения дополнительной работы. 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

Вот оператор создания таблицы, иллюстрирующий исключение:

Java-программа вызывает ошибку:

Приведенный выше код выводит для меня этот вывод:

Обходные пути:

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

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

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

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

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

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

Источник

Я получил эту ошибку, используя 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 сделал вас мягким в середине, позволяя вам делать глупые вещи и игнорировать его.

In this post, I will tell you how to fix the error that PostgreSQL throws when you try to execute an SQL-statement.

When you execute a non-correct SQL statement, you correct it and try to execute it again, you can have an error like: ERROR: current transaction is aborted, commands ignored until end of transaction block

By executing that wrong SQL-statement, postgreSQL will not terminate the execution by itself so you need to rollback manually. You can do this by simply execute the following statement:

rollback;

Example

I want to execute the non-correct SQL-statement:

select * from account

PostgreSQL will throw the following error: syntax error at or near ‘fro’. This means my word ‘from’ is not correctly typed. So I now want to execute the correct statement:

select * from account

Here, PostgreSQL will throw the following error: current transaction is aborted, commands ignored until end of transaction block. This is because the wrong SQL-statement is still trying to commit. Now, to rollback, type the following SQL-statement:

rollback;

Now we can try to execute the correct SQL-statement again. You will notice that it works this time. Enjoy 😀

I installed OSQA and I synchronized (syncdb and migrate) the databases and I restarted Apache.
In the browser I got the HTTP Status 200 Error and in the project logs I got a lot of errors with this message:

DatabaseError: current transaction is aborted, commands ignored until end of transaction block

I also found these errors in PostgreSQL‘s logs:

LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
ERROR:  relation "forum_keyvalue" does not exist at character 85
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MIN_NUMBER_OF_TAGS' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MIN_NUMBER_OF_TAGS' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MAX_NUMBER_OF_TAGS' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MAX_NUMBER_OF_TAGS' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'MIN_USERNAME_LENGTH' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'MIN_USERNAME_LENGTH' 
LOG:  statement: SELECT "forum_badge"."id" FROM "forum_badge"
ERROR:  current transaction is aborted, commands ignored until end of transaction block

I searched for a solution to the problem on StackOverflow and I found it:

To get rid of the error, roll back the last (erroneous) transaction
after you’ve fixed your code:

from django.db import transaction transaction.rollback()

This solution doesn’t work for me.
I running my application on Python2.7, Django-1.3.7 and PostgreSQL 9.1.11.
Any help is appreciated! Thank you very much and sorry for my bad english.

I installed OSQA and I synchronized (syncdb and migrate) the databases and I restarted Apache.
In the browser I got the HTTP Status 200 Error and in the project logs I got a lot of errors with this message:

DatabaseError: current transaction is aborted, commands ignored until end of transaction block

I also found these errors in PostgreSQL‘s logs:

LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
ERROR:  relation "forum_keyvalue" does not exist at character 85
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MIN_NUMBER_OF_TAGS' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MIN_NUMBER_OF_TAGS' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MAX_NUMBER_OF_TAGS' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_MAX_NUMBER_OF_TAGS' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'FORM_EMPTY_QUESTION_BODY' 
LOG:  statement: SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'MIN_USERNAME_LENGTH' 
ERROR:  current transaction is aborted, commands ignored until end of transaction block
STATEMENT:  SELECT "forum_keyvalue"."id", "forum_keyvalue"."key", "forum_keyvalue"."value" FROM "forum_keyvalue" WHERE "forum_keyvalue"."key" = 'MIN_USERNAME_LENGTH' 
LOG:  statement: SELECT "forum_badge"."id" FROM "forum_badge"
ERROR:  current transaction is aborted, commands ignored until end of transaction block

I searched for a solution to the problem on StackOverflow and I found it:

To get rid of the error, roll back the last (erroneous) transaction
after you’ve fixed your code:

from django.db import transaction transaction.rollback()

This solution doesn’t work for me.
I running my application on Python2.7, Django-1.3.7 and PostgreSQL 9.1.11.
Any help is appreciated! Thank you very much and sorry for my bad english.

Я считаю, что ответ @AnujGupta правильный. Однако откат сам по себе может вызвать исключение, которое вы должны перехватить и обработать:

from django.db import transaction, DatabaseError
try:
    a.save()
except DatabaseError:
    try:
        transaction.rollback()
    except transaction.TransactionManagementError:
        # Log or handle otherwise

Если вы обнаружите, что переписываете этот код в различных save() местоположения, вы можете извлечь метод:

import traceback
def try_rolling_back():
    try:
        transaction.rollback()
        log.warning('rolled back')  # example handling
    except transaction.TransactionManagementError:
        log.exception(traceback.format_exc())  # example handling

Наконец, вы можете преобразить его с помощью декоратора, который защищает методы, использующие save():

from functools import wraps
def try_rolling_back_on_exception(fn):
    @wraps(fn)
    def wrapped(*args, **kwargs):
        try:
            return fn(*args, **kwargs)
        except:
            traceback.print_exc()
            try_rolling_back()
    return wrapped

@try_rolling_back_on_exception
def some_saving_method():
    # ...
    model.save()
    # ...

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

Доброго всем!

Второй день играюсь с постгрессом, вчепятления после ms прекрасные
Но.

Работаю pgAdmin
Создаю базу данных
Создаю в базе таблицу
Пытаюсь из c# (npgsql) добавить запись, ругается «ключ не может быть null»
Хлопаю себя по лбу, открываю свойства таблицы, свойства поля id_pk, в «определениях» Identity ставлю увеличение 1, сохраняю.

И всё… на любой запрос «ОШИБКА: текущая транзакция прервана, команды до конца блока транзакции игнорируются»
Не то что что-то сделать, на любое шевеление мышкой, на попытку посмотреть другую таблицу, на попытку посмотреть свойства базы, реакция одна «ОШИБКА: текущая транзакция прервана, команды до конца блока транзакции игнорируются»

«Попинать окно», в смысле перезагрузил pgAdmin, даже раскрыть в интерфейсе дерево элементов базы не могу!
Пришлось удалять базу и создавать заново. Хорошо, что это учебный процесс.

Но чото как-то стало боязно. Кто-нибудь может объяснить что я вообще поломал? И как с этим бороться?

В этих ихних интернетах, рецепты вполне понятные например https://dstarod.github.io/term… -postgres/
Но я даже окна для запуска SQL запроса в pgAdmin открыть не мог!

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Error ошибка приложения invalid index
  • Ets ошибка мерседес w210