如何 avoid/fix django 的 DatabaseTransactionError
How to avoid/fix django's DatabaseTransactionError
我有以下(释义)代码受竞争条件的影响:
def calculate_and_cache(template, template_response):
# run a fairly slow and intensive calculation:
calculated_object = calculate_slowly(template, template_response)
cached_calculation = Calculation(calculated=calculated_object,
template=template,
template_response=template_response)
# try to save the calculation just computed:
try:
cached_calculation.save()
return cached_calculation
# if another thread beat you to saving this, catch the exception
# but return the object that was just calculated
except DatabaseError as error:
log(error)
return cached_calculation
它引发了 DatabaseTransactionError:
TransactionManagementError: An error occurred in the current transaction.
You can't execute queries until the end of the 'atomic' block.
The docs 对 DTE 的评价:
当退出一个原子块时,Django 会查看它是正常退出还是异常退出来决定是提交还是回滚....如果你试图运行 数据库查询在回滚发生之前,Django 将引发 TransactionManagementError。
但是 they 也有关于它们的更模糊的说法:
TransactionManagementError 是针对与数据库事务相关的所有问题而引发的。
我的问题,按普遍性升序排列:
- 捕获
DatabaseError
是否会通过让 save()
在返回对象的同时优雅地退出来真正解决竞争条件?
- 上述代码中的原子块从哪里开始到哪里结束?
- 我做错了什么,我该如何解决?
controlling transactions explicitly 上的 Django 文档有一个在原子块中捕获异常的示例。
在你的情况下,你似乎根本没有使用 atomic
装饰器,所以首先你需要添加所需的导入。
from django.db import transaction
然后您需要将可能引发数据库错误的代码移动到原子块中:
try:
with transaction.atomic():
cached_calculation.save()
return cached_calculation
# if another thread beat you to saving this, catch the exception
# but return the object that was just calculated
except DatabaseError as error:
log(error)
return cached_calculation
我有以下(释义)代码受竞争条件的影响:
def calculate_and_cache(template, template_response):
# run a fairly slow and intensive calculation:
calculated_object = calculate_slowly(template, template_response)
cached_calculation = Calculation(calculated=calculated_object,
template=template,
template_response=template_response)
# try to save the calculation just computed:
try:
cached_calculation.save()
return cached_calculation
# if another thread beat you to saving this, catch the exception
# but return the object that was just calculated
except DatabaseError as error:
log(error)
return cached_calculation
它引发了 DatabaseTransactionError:
TransactionManagementError: An error occurred in the current transaction.
You can't execute queries until the end of the 'atomic' block.
The docs 对 DTE 的评价:
当退出一个原子块时,Django 会查看它是正常退出还是异常退出来决定是提交还是回滚....如果你试图运行 数据库查询在回滚发生之前,Django 将引发 TransactionManagementError。
但是 they 也有关于它们的更模糊的说法:
TransactionManagementError 是针对与数据库事务相关的所有问题而引发的。
我的问题,按普遍性升序排列:
- 捕获
DatabaseError
是否会通过让save()
在返回对象的同时优雅地退出来真正解决竞争条件? - 上述代码中的原子块从哪里开始到哪里结束?
- 我做错了什么,我该如何解决?
controlling transactions explicitly 上的 Django 文档有一个在原子块中捕获异常的示例。
在你的情况下,你似乎根本没有使用 atomic
装饰器,所以首先你需要添加所需的导入。
from django.db import transaction
然后您需要将可能引发数据库错误的代码移动到原子块中:
try:
with transaction.atomic():
cached_calculation.save()
return cached_calculation
# if another thread beat you to saving this, catch the exception
# but return the object that was just calculated
except DatabaseError as error:
log(error)
return cached_calculation