繁体   English   中英

DatabaseError:当前事务被中止,在事务块结束之前忽略命令?

[英]DatabaseError: current transaction is aborted, commands ignored until end of transaction block?

我收到了很多错误消息:

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

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

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

当查询产生错误并且您尝试运行另一个查询而不首先回滚事务时,这就是 postgres 所做的。 (您可能会将其视为一项安全功能,以防止您破坏数据。)

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

要消除错误,请在修复代码后回滚最后一个(错误的)事务

from django.db import transaction
transaction.rollback()

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

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

参考: Django 文档

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

要同步您的 django 数据库,请从您的应用程序目录中的终端中键入:

$ python manage.py syncdb

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

快乐编码!

在 Flask 中你只需要写:

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

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

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

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不会破坏事务。

这里的教训是不要尝试/除外/通过。

我认为牧师提到的模式更有可能是使用 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/ 开发/参考/数据库/#autocommit-mode

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

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

只需使用回滚

示例代码

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);")

如果您在交互式 shell 中遇到此问题并需要快速修复,请执行以下操作:

from django.db import connection
connection._rollback()

最初在这个答案中看到

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

COMMIT;

我在这里遇到了类似的错误。 我在这个链接https://www.postgresqltutorial.com/postgresql-python/transaction/中找到了答案

client = PsqlConnection(config)
connection = client.connection
cursor = client.cursor

try:
   for query in list_of_querys:
      #query format => "INSERT INTO <database.table> VALUES (<values>)"
      cursor.execute(query)
      connection.commit()
except BaseException as e:
   connection.rollback()

执行此操作后,您发送到 postgresql 的以下查询不会返回错误。

我有 silimar 问题。 解决方案是迁移数据库( manage.py syncdbmanage.py schemamigration --auto <table name>如果您使用南)。

在 Flask shell 中,我需要做的就是使用session.rollback()来解决这个问题。

你只需要运行

rollback;

在 PostgreSQL 中,就是这样!

我遇到了这个问题,由于错误事务没有正确结束而出现错误,我在这里找到了事务控制命令的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来结束错误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

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

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

我必须通过代码调试才能显示上述消息,否则会显示

DatabaseError: current transaction is aborted

回应@priestc 和@Sebastian,如果你做这样的事情怎么办?

try:
    conn.commit()
except:
    pass

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

我刚刚尝试了这段代码,它似乎可以工作,默默地失败而不必关心任何可能的错误,并且在查询良好时工作。

我相信@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()保留为提取方法仍然很方便,以防您需要在需要特定处理的情况下手动使用它,而通用装饰器处理还不够。

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

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

我正在使用 python 包 psycopg2 并且在查询时出现此错误。 我一直只运行查询,然后运行执行函数,但是当我重新运行连接(如下所示)时,它解决了问题。 因此,重新运行脚本之上的内容,即连接,因为正如上面有人所说,我认为它丢失了连接或不同步或其他原因。

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

这是一个错误的 sql 执行问题,它不允许其他查询执行,直到前一个查询被挂起/回滚。

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

在此处输入图片说明

您可以通过“set_isolation_level(0)”禁用事务

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM