DatabaseError: текущая транзакция прервана, команды игнорируются до конца блока транзакции? - PullRequest
223 голосов
/ 05 июня 2010

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

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

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

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

Ответы [ 17 ]

1 голос
/ 21 апреля 2014

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

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 голос
/ 27 марта 2014

Я считаю, что ответ @ 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 голос
/ 14 февраля 2013

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

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

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

DatabaseError: current transaction is aborted
1 голос
/ 17 мая 2013

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

try:
    conn.commit()
except:
    pass

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

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

1 голос
/ 26 сентября 2018

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

0 голосов
/ 05 июля 2019

Я столкнулся с этой проблемой, ошибка появляется, так как транзакции с ошибками не были правильно завершены, я нашел 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
0 голосов
/ 08 декабря 2011

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

...