数据库错误:当前事务被中止,命令被忽略,直到事务块结束?

我收到了很多错误的信息:

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

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

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

316369 次浏览

当查询产生错误,而您试图在不先回滚事务的情况下运行另一个查询时,postgres就会这样做。(你可能会认为这是一个安全功能,防止你破坏你的数据。)

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

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

要同步你的django db,在你的app目录中,在终端中,输入:

$ python manage.py syncdb

编辑:注意,如果你正在使用django-south,运行'$ python manage.py migrate'命令也可以解决这个问题。

编码快乐!

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

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

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

第二个查询没有问题,但是由于捕获了真正的错误,第二个查询将引发(信息量少得多的)错误。

edit:只有当except子句捕获到IntegrityError(或任何其他低级数据库异常)时,才会发生这种情况。如果捕获到类似DoesNotExist的异常,则不会出现此错误,因为DoesNotExist不会破坏事务。

这里的教训是不要尝试/except/pass。

我认为在使用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,
}
}

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

我也遇到了类似的问题。解决方案是迁移db (manage.py syncdbmanage.py schemamigration --auto <table name>,如果你使用南部)。

为了消除错误,在你修复了你的代码后,回滚最后一个(错误的)事务:

from django.db import transaction
transaction.rollback()

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

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

参考:Django的文档

我也有这个错误,但它掩盖了另一个更相关的错误消息,代码试图在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

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

如果你在交互式shell中得到这个,需要快速修复,请这样做:

from django.db import connection
connection._rollback()

最初见于这个答案

我相信@AnujGupta的答案是正确的。然而,回滚本身会引发一个异常,你应该捕获和处理:

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

如果你发现你在不同的save()位置重写这段代码,你可以extract-method:

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

我在postgres终端上运行故障事务时遇到了类似的行为。在此之后没有任何操作,因为database处于error的状态。然而,作为一个快速修复,如果你能够避免rollback transaction. .以下是我的诀窍:

COMMIT;

只需使用回滚

示例代码

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

在Flask中,你只需要写:

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

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

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

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

我正在使用python包psycopg2,我在查询时得到了这个错误。 我一直只运行查询,然后运行execute函数,但是当我重新运行连接(如下所示)时,它解决了这个问题。所以重新运行你的脚本上面的内容,即连接,因为正如上面有人说的,我认为它失去了连接或不同步或其他

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

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

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

enter image description here

你只需要跑

rollback;

在PostgreSQL中,就是这样!

这里也有类似的错误。我在这个链接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的以下查询将不会返回错误。