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

Я получил эту ошибку, используя Java и postgresql, делая вставку в таблицу. Я проиллюстрирую, как... Вопрос по теме: postgresql, jboss, infinispan.

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

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

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

Резюме:

Причина, по которой вы получаете эту ошибку, заключается в том, что вы ввели транзакцию, и один из ваших 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

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

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

Я получил много ошибок с сообщением:

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

После изменения с python-psycopg на python-psycopg2 в качестве движка базы данных проекта Django.

Код остается прежним, просто не знаю, откуда эти ошибки.

17 ответов

Лучший ответ

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

Чтобы это исправить, вам нужно выяснить, где в коде выполняется неверный запрос. Может быть полезно использовать log_statement и log_min_error_statement опции на вашем сервере postgresql.


170

ʇsәɹoɈ
31 Окт 2018 в 20:34

Я столкнулся с этой проблемой, ошибка появляется, поскольку транзакции с ошибками не были правильно завершены, я нашел postgresql_transactions команды управления транзакциями здесь

Контроль транзакций

Следующие команды используются для управления транзакциями

BEGIN TRANSACTION − To start a transaction.

COMMIT − To save the changes, alternatively you can use END TRANSACTION command.

ROLLBACK − To rollback the changes.

Поэтому я использую END TRANSACTION, чтобы завершить транзакцию ошибки, код такой:

    for key_of_attribute, command in sql_command.items():
        cursor = connection.cursor()
        g_logger.info("execute command :%s" % (command))
        try:
            cursor.execute(command)
            rows = cursor.fetchall()
            g_logger.info("the command:%s result is :%s" % (command, rows))
            result_list[key_of_attribute] = rows
            g_logger.info("result_list is :%s" % (result_list))
        except Exception as e:
            cursor.execute('END TRANSACTION;')
            g_logger.info("error command :%s and error is :%s" % (command, e))
    return result_list


1

Adam
5 Июл 2019 в 05:21

Если вы получили это, находясь в интерактивной оболочке, и хотите быстро исправить это, сделайте следующее:

from django.db import connection
connection._rollback()

Первоначально видели в этом ответе


6

Community
23 Май 2017 в 12:26

Чтобы избавиться от ошибки, откатите последнюю (ошибочную) транзакцию после исправления кода:

from django.db import transaction
transaction.rollback()

Вы можете использовать try-кроме, чтобы предотвратить возникновение ошибки:

from django.db import transaction, DatabaseError
try:
    a.save()
except DatabaseError:
    transaction.rollback()

См. документацию Django.


131

Anuj Gupta
21 Янв 2016 в 16:56

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

Чтобы синхронизировать вашу django db, в каталоге вашего приложения, в терминале, введите:

$ python manage.py syncdb

Изменить: Обратите внимание, что если вы используете django-south, запуск команды ‘$ python manage.py migrate’ также может решить эту проблему.

Удачного кодирования!


50

Michael Merchant
22 Май 2012 в 20:12

Просто используйте откат

Пример кода

try:
    cur.execute("CREATE TABLE IF NOT EXISTS test2 (id serial, qa text);")
except:
    cur.execute("rollback")
    cur.execute("CREATE TABLE IF NOT EXISTS test2 (id serial, qa text);")


3

Umer
29 Янв 2018 в 14:05

У меня похожая проблема. Решением было перенести db (manage.py syncdb и manage.py schemamigration --auto <table name>, если вы используете юг).


5

Daniil Ryzhkov
2 Авг 2012 в 07:55

Вы можете отключить транзакцию через «set_isolation_level (0)»


-5

springrider
8 Дек 2011 в 02:43

В оболочке Flask все, что мне нужно было сделать, это session.rollback(), чтобы обойти это.


1

watsonic
29 Сен 2018 в 01:06

Я считаю, что ответ @ 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() в качестве извлеченного метода на тот случай, если вам понадобится использовать его вручную в тех случаях, когда требуется особая обработка, а обычной обработки декоратора недостаточно.


1

Jonathan
27 Мар 2014 в 21:02

По моему опыту, эти ошибки происходят следующим образом:

try:
    code_that_executes_bad_query()
    # transaction on DB is now bad
except:
    pass

# transaction on db is still bad
code_that_executes_working_query() # raises transaction error

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

Редактировать: это происходит только в том случае, если условие except ловит IntegrityError (или любое другое исключение базы данных низкого уровня). Если вы поймаете что-то вроде DoesNotExist, эта ошибка не возникнет, потому что {{X3 }} не портит транзакцию.

Урок здесь — не пытайтесь / кроме / проходите.


34

priestc
13 Ноя 2012 в 20:09

У меня тоже была эта ошибка, но она маскировала еще одно более важное сообщение об ошибке, в котором код пытался сохранить строку из 125 символов в столбце из 100 символов:

DatabaseError: value too long for type character varying(100)

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

DatabaseError: current transaction is aborted


1

Thierry Lam
13 Фев 2013 в 21:57

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

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

try:
    profile = user.get_profile()
except ObjectDoesNotExist:
    profile = make_default_profile_for_user(user)

do_something_with_profile(profile)

Если вы чувствуете себя нормально с этим шаблоном, но хотите избежать явного кода обработки транзакций повсюду, тогда вам может потребоваться включить режим автоматической фиксации (PostgreSQL 8.2+): https://docs.djangoproject.com/en/dev/ref/databases/#autocommit-mode

DATABASES['default'] = {
    #.. you usual options...
    'OPTIONS': {
        'autocommit': True,
    }
}

Я не уверен, есть ли важные соображения производительности (или любого другого типа).


16

priestc
13 Ноя 2012 в 20:05

Это очень странное поведение для меня. Я удивлен, что никто не думал о точках сохранения. В моем коде ошибочный запрос был ожидаемым поведением:

from django.db import transaction
@transaction.commit_on_success
def update():
    skipped = 0
    for old_model in OldModel.objects.all():
        try:
            Model.objects.create(
                group_id=old_model.group_uuid,
                file_id=old_model.file_uuid,
            )
        except IntegrityError:
            skipped += 1
    return skipped

Я изменил код таким образом, чтобы использовать точки сохранения:

from django.db import transaction
@transaction.commit_on_success
def update():
    skipped = 0
    sid = transaction.savepoint()
    for old_model in OldModel.objects.all():
        try:
            Model.objects.create(
                group_id=old_model.group_uuid,
                file_id=old_model.file_uuid,
            )
        except IntegrityError:
            skipped += 1
            transaction.savepoint_rollback(sid)
        else:
            transaction.savepoint_commit(sid)
    return skipped


1

radtek
9 Янв 2015 в 13:54

Я столкнулся с подобным поведением при выполнении сбойной транзакции на терминале postgres. После этого ничего не произошло, поскольку database находится в состоянии error. Однако, как быстрое решение, если вы можете позволить себе избежать rollback transaction. Следующее сделало трюк для меня:

COMMIT;


6

faizanjehangir
11 Мар 2016 в 21:53

В ответ на @priestc и @Sebastian, что если вы сделаете что-то подобное?

try:
    conn.commit()
except:
    pass

cursor.execute( sql )
try: 
    return cursor.fetchall()
except: 
    conn.commit()
    return None

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


1

Nate
17 Май 2013 в 15:21

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Error writing fat
  • Error using mldivide matrix dimensions must agree
  • Error недостаточно памяти саи
  • Error writing etc fstab read only file system
  • Error using matlab internal math interp1 sample points must be unique

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

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