【发布时间】:2014-03-30 00:23:42
【问题描述】:
我在 django 1.6 中使用 transaction.atomic 作为事务的上下文管理器。有一个代码块,我想在一个事务中,它有几个网络调用和一些数据库写入。我看到非常奇怪的行为。每隔一段时间(可能是 20 次中的 1 次),我注意到发生了部分回滚,没有引发任何异常,并且视图执行时没有任何错误。我的应用程序托管在 heroku 上,我们使用 heroku postgres v9.2.8。伪代码:
from django.db import transaction
def some_view(request):
try:
with transation.atomic():
network_call_1()
db_write_1.save(update_fields=['col4',])
db_write_2.save(update_fields=['col3',])
db_write_3.save(update_fields=['col1',])
network_call_2()
db_write_4.save(update_fields=['col6',])
db_write_5.bulk_create([object1, object2])
db_write_6.bulk_create([object1, object2])
except Exception, e:
logger.error(e)
return HttpResponse()
我注意到的行为是,没有任何异常被引发,要么 db write 1-3 已回滚,其余部分已完成,要么 db write 1 已回滚,其余部分已完成,依此类推。我不明白为什么会发生这种情况。首先,如果有回滚,不应该是事务的完整回滚吗?如果有回滚,是否也不应该引发异常以便我知道发生了回滚?每次发生这种情况时,都不会引发异常,代码只是继续执行并返回成功的 HttpResponse。
相关设置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydb',
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'localhost',
'PORT': '5432',
},
}
CONN_MAX_AGE = None
这个错误让我很困惑。任何线索都会有很大帮助!
【问题讨论】:
-
我删除了我的答案,因为@almalki 证明我对文档的理解是错误的。但是,我认为这里的主要问题是您没有遇到异常,因此您不知道出了什么问题。为此,您模棱两可的
try块可能正在吞噬一个内部错误似乎仍然是合理的(至少对我而言)。你能至少试试我的建议,并告诉我这是否重要? -
另外——你可能在使用
autocommit=False吗? -
Django 1.6 默认使用 autocommit=True。我还没有将其设置为 False。除非我对默认行为有误,否则我认为就自动提交而言我很好。尝试在事务块之外。即使错误被默默吞噬,整个事务也应该回滚。除非明确执行,否则不会发生部分回滚。这就是我对此感到困惑的主要原因。
-
是的,自动提交默认为 True。我之所以问,是因为 django 1.6.2 引入了针对
autcommit=False问题的修复程序...好吧,无论如何,我不知道是什么问题,但也许可以尝试将autocommit=True添加到您的数据库配置 (here's how) 所以它将在数据库级别强制执行。也许这会有所帮助 -
重现性如何?我会通过设置 PostgreSQL log_statements='all' 来解决这个问题,这样我就可以准确地看到向 PostgreSQL 发出的命令序列是什么。
标签: django postgresql heroku transactions