DatabaseError:当前事务被中止,命令被忽略直到事务块结束

时间:2010-06-05 06:05:19

标签: python django postgresql psycopg2 psycopg

我收到了很多错误消息:

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

从python-psycopg更改为python-psycopg2作为Django项目的数据库引擎。

代码保持不变,只是不知道这些错误来自哪里。

19 个答案:

答案 0 :(得分:156)

这是postgres在查询产生错误并且您尝试在没有先回滚事务的情况下运行另一个查询时所执行的操作。 (您可能会将其视为安全功能,以防止您破坏数据。)

要解决此问题,您需要确定代码中正在执行错误查询的位置。在postgresql服务器中使用log_statementlog_min_error_statement选项可能会有所帮助。

答案 1 :(得分:128)

要解决错误,在您修复代码后回滚最后一次(错误的)交易

from django.db import transaction
transaction.rollback()

您可以使用try-except来防止错误发生:

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

参考:Django documentation

答案 2 :(得分:50)

所以,我遇到了同样的问题。我在这里遇到的问题是我的数据库没有正确同步。简单的问题似乎总是引起最大的焦虑......

要在您的app目录中,在终端内同步您的django数据库,请输入:

$ python manage.py syncdb

编辑:请注意,如果您使用的是django-south,则运行'$ python manage.py migrate'命令也可以解决此问题。

快乐的编码!

答案 3 :(得分:30)

根据我的经验,这些错误就是这样发生的:

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的内容,则此错误不会出现,因为DoesNotExist不会破坏交易。

这里的教训是不要尝试/除/传。

答案 4 :(得分:16)

我认为使用PostgreSQL时,priestc提到的模式更可能是导致此问题的常见原因。

但是我觉得模式有用,我不认为这个问题应该是一直避免它的原因。例如:

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,
    }
}

我不确定是否存在重要的性能考虑(或任何其他类型)。

答案 5 :(得分:16)

在Flask中你只需要写:

curs = conn.cursor()
curs.execute("ROLLBACK")
conn.commit()

P.S。文档在这里https://www.postgresql.org/docs/9.4/static/sql-rollback.html

答案 6 :(得分:6)

如果您在交互式shell中获得此功能并需要快速修复,请执行以下操作:

from django.db import connection
connection._rollback()

最初见于this answer

答案 7 :(得分:6)

我在postgres终端上运行故障的事务时遇到了类似的行为。在此之后没有任何事情发生,因为database处于error状态。但是,作为一个快速解决方案,如果您能够避免rollback transaction。以下为我做了诀窍:

COMMIT;

答案 8 :(得分:2)

只需使用回滚

示例代码

<span>

答案 9 :(得分:1)

我相信@ 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()保留为提取的方法,以防您需要手动使用它来处理需要特定处理的情况,并且通用装饰器处理不够

答案 10 :(得分:1)

我正在使用python软件包psycopg2,查询时出现此错误。 我一直只运行查询,然后运行execute函数,但是当我重新运行连接(如下所示)时,它解决了该问题。因此,请重新运行脚本上方的内容(即连接),因为如上所述,我认为它失去了连接或不同步或什么原因。

connection = psycopg2.connect(user = "##",
        password = "##",
        host = "##",
        port = "##",
        database = "##")
cursor = connection.cursor()

答案 11 :(得分:1)

在Flask外壳程序中,我需要做的就是session.rollback()才能克服这个问题。

答案 12 :(得分:1)

这对我来说是非常奇怪的行为。我很惊讶没有人想到保存点。在我的代码中,失败的查询是预期的行为:

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

答案 13 :(得分:1)

回应@priestc和@Sebastian,如果你这样做会怎么样?

try:
    conn.commit()
except:
    pass

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

我刚尝试过这段代码,它似乎可以正常工作,无需担心任何可能的错误而无声地失败,并在查询良好时正常工作。

答案 14 :(得分:1)

我也遇到了这个错误,但它掩盖了另一个更相关的错误消息,其中代码试图在100个字符的列中存储125个字符的字符串:

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

我必须通过代码调试上面显示的消息,否则显示

DatabaseError: current transaction is aborted

答案 15 :(得分:0)

我遇到了这个问题,由于错误事务未正确结束,错误出现了,我发现事务控制命令herepostgresql_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结束错误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

答案 16 :(得分:0)

这是SQL执行错误的问题,在上一个被暂停/回滚之前,不允许其他查询执行。

在PgAdmin4-4.24中,有一个回滚选项,可以尝试一下。

enter image description here

答案 17 :(得分:0)

您只需要运行

rollback;

就是这样..在PostreSQL

答案 18 :(得分:-5)

您可以通过“set_isolation_level(0)”

禁用交易