Django+Postgres:"当前事务已中止,直到事务块结束后命令才会被忽略"

83

我开始在一个Django/Postgres网站上工作。有时我会在manage.py shell中工作,并意外地执行一些导致错误的数据库操作。然后我就无法执行任何数据库操作,因为我尝试执行的每个数据库操作都会出现以下错误:

current transaction is aborted, commands ignored until end of transaction block

我的当前解决方法是重新启动shell,但我应该找到一种方法在不放弃shell会话的情况下解决这个问题。

(我已经阅读了 这篇文章这篇文章,但它们没有提供从shell中执行的可行指令。)


2
我以前遇到过这个问题,找不到解决的办法... - Hoff
1
可能是重复的问题,与此链接几乎完全相同,已有可接受的解决方案... - Cerin
13个回答

127

6
这个解决方案对我没有用。即使回滚了事务,我也无法再与数据库进行任何交互。我找到了另一个解决方法,请参见我的答案。 - Wolkenarchitekt
2
如果 _rollback 对你不起作用,还有 connection.close() (@ifischer)。 - hobs

33

有时候我也会遇到这种情况,通常是因为缺少了一个闭合标签

manage.py migrate 
或者
manage.py syncdb

如此也可以发生反过来的情况,如果你的models.py中存在一个待处理的schemamigration。使用south时,你需要通过以下方式更新模式:

manage.py schemamigration mymodel --auto

13

点击这里

通常的快速解决方法是通过添加以下内容来开启数据库级别的自动提交:

'OPTIONS': {'autocommit': True,}

前往数据库设置。


在哪里?你要把它添加到哪里? - dviljoen
在设置文件中,位于DATABASES字典内:https://docs.djangoproject.com/en/dev/ref/settings/#autocommit。 - Ignacio Pérez
这些信息似乎已经过时了。从文档中可以看到:“Django的默认行为是在自动提交模式下运行...出于性能原因,Django的TestCase类还会将每个测试用例包装在一个事务中。” - shacker

3

警告:以下补丁可能会导致数据库中的事务处于打开状态(至少在postgres中是如此)。我不确定这一点(以及如何修复),但我强烈建议不要在生产数据库上执行以下补丁。

由于被接受的答案不能解决我的问题-一旦我遇到任何数据库错误,我就无法进行任何新的数据库操作,即使手动回滚-所以我想出了自己的解决方案。

当我运行Django-shell时,我会对Django进行补丁,以便在发生任何错误时立即关闭DB连接。这样我就不必考虑回滚事务或处理连接的问题。

这是我在Django-shell会话开始时加载的代码:

from django import db
from django.db.backends.util import CursorDebugWrapper
old_execute = CursorDebugWrapper.execute
old_execute_many = CursorDebugWrapper.executemany

def execute_wrapper(*args, **kwargs):
    try:
        old_execute(*args, **kwargs)
    except Exception, ex:
        logger.error("Database error:\n%s" % ex)
        db.close_connection()

def execute_many_wrapper(*args, **kwargs):
    try:
        old_execute_many(*args, **kwargs)
    except Exception, ex:
        logger.error("Database error:\n%s" % ex)
        db.close_connection()

CursorDebugWrapper.execute = execute_wrapper
CursorDebugWrapper.executemany = execute_many_wrapper

2
如果有人感兴趣:我扩展了django-extensions shell-plus命令,使其能够在启动时加载文件,在其中包括此补丁以及其他内容。https://github.com/ifischer/django-extensions - Wolkenarchitekt
2
这肯定会留下连接,因为django.db.close_connection是一个函数,如果你想让它做任何事情,就需要用()调用它;) 我经常使用django.db.connection.close(),可能会被别名为close_connection,不确定。 - hobs

3

我在将备份还原到完全空的数据库后遇到了这个错误。运行以下命令后错误消失了:

./manage syncdb 

也许在这个转储中缺少一些内部模型...

2
对我来说,这是一个没有迁移的测试数据库。我在测试时使用了--keepdb。运行一次没有使用它就解决了错误。

1
这个话题上有很多有用的答案,但是要找出问题的根源仍然是一个挑战。因此,我将尝试在如何找到解决方案的更多背景信息上提供一些上下文。
特别针对Django,您需要打开db查询日志,并在错误被引发之前,在控制台中找到失败的查询。直接在数据库上运行该查询,您就会看到问题所在。
在我的情况下,数据库中缺少了一列,所以在迁移后一切正常工作。
希望这对您有所帮助。

0
我将以下内容添加到我的设置文件中,因为当我“玩耍”时,我喜欢自动提交功能,但在我的网站运行时不希望它处于活动状态。
所以为了只在Shell中获得自动提交功能,我做了这个小技巧:
import sys
if 'shell' in sys.argv or sys.argv[0].endswith('pydevconsole.py'):
    DATABASES['default']['OPTIONS']['autocommit'] = True

注意:第二部分是因为我使用PyCharm工作,它不能直接运行manage.py文件。


0
在我的情况下,这是因为我有一个迁移文件,但我没有将其应用到数据库中。我通过执行python manage.py migrate(或python3 manage.py migrate)来解决它。

0

如果在运行migrate(South)时遇到此类错误,可能是因为您的数据库模式中有很多更改,并且希望一次性处理它们。Postgres对此有点讨厌。始终有效的方法是将一个大型迁移拆分为较小的步骤。最有可能的是,您正在使用版本控制系统。

  • 您当前的版本
  • 提交n1
  • 提交n2
  • 提交n3
  • 提交n4#数据库更改
  • 提交n5
  • 提交n6
  • 提交n7#数据库更改
  • 提交n8
  • 提交n9#数据库更改
  • 提交n10

因此,针对上述情况,请按照以下步骤操作:

  • 将存储库检出到“n4”,然后进行同步和迁移。
  • 将存储库检出到“n7”,然后进行同步和迁移。
  • 将存储库检出到“n10”,然后进行同步和迁移。

然后你就完成了。 :)

它应该无缝运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接