前一段时间在sentry上看到了这样一个错误“django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.”。这是我第一次看到这种类型的错误。看了一下报错的代码。
def buggy_code():
with transaction.atomic():
try:
do_something()
except:
pass
do_something2()
do_something()
里面有数据库写操作,于是猜测数据库执行do_something()里的写操作时发生错误django抛了异常,但是被catch住了,代码走到do_something2()时进行数据库操作时,抛出了上述错误。
写了一小段代码验证猜想。
with transaction.atomic():
try:
UserBaseInfo.objects.filter(user_id=2).update(user_id=1)
except Exception as e:
print e
print UserBaseInfo.objects.get(id=90)
在此代码执行前,数据库userbaseinfo
这张表里已存在user_id=1的记录,并且该字段有唯一性限制。
运行之,报错django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block,和预想的一致。
总结一下,数据库在执行do_something()
中的某一写操作时发生了错误。但是业务代码里try except捕获了异常但是没有将异常抛出,而是静默处理。代码顺利执行至do_something2()
,在执行do_something2()
中的数据库请求时,django向数据库发送rollback请求,并抛出异常。