django - 当 Django 将可序列化事务隔离级别与 postgresql 一起使用时,哪些特定异常表示序列化失败?
问题描述
有时需要为 Django 中的数据库操作使用比默认的“已提交读”更高的隔离级别。 文档警告说:
在更高的隔离级别下,您的应用程序应该准备好处理因序列化失败而引发的异常。
但是哪些特定异常表明序列化失败,而不是查询或事务的其他问题?
序列化失败后的简单重试机制可能如下所示:
for retries in range(0, 3):
try:
with transaction.atomic():
MyModel.objects.update(foo='bar')
except StuffHappened:
continue
else:
break
应该替换哪些特定异常,StuffHappened
以便只有序列化失败而不是其他异常会导致重试?
Django 有多种Database Exceptions和Transaction Exceptions。其中一个/一些可能代表序列化失败吗?
我对此特别感兴趣。
解决方案
嗯,好问题。该文档暗示适当的例外是TransactionManagementError
:
TransactionManagementError
针对与数据库事务相关的任何和所有问题提出。
但是,源代码提供了一个强有力的线索,表明它不是:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
请注意,这是一个ProgrammingError
,它确实用于指示程序员错误(即“使用不当”)。
如果我们查看 psycopg(用于 PostgreSQL 支持的 Python 适配器)的文档,我们会看到它会引发psycopg2.extensions.TransactionRollbackError
:
异常
psycopg2.extensions.TransactionRollbackError
(子类OperationalError
)导致事务回滚的错误(死锁、序列化失败等)。
但是 Django 对此做了什么?好吧,如此处所述,它将标准 Python DB API 2.0 异常包装在 Django 等效项中,并将__cause__
属性设置为原始异常。因此,以下可能是您可以进行的最具体的检查:
from django.db import OperationalError
from psycopg2.extensions import TransactionRollbackError
for retries in range(0, 3):
try:
with transaction.atomic():
MyModel.objects.update(foo='bar')
except OperationalError as e:
if e.__cause__.__class__ == TransactionRollbackError:
continue
else:
raise
else:
break
根据 PostgreSQL 公开的错误详细信息(可通过 获得e.__cause__.diag
),可能会编写更具体的测试。
不过,一般来说,Python DB API 2.0 文档指出这OperationalError
确实是事务问题的正确异常类型,因此希望捕获它是一个合理有效的与数据库无关的解决方案。
推荐阅读
- r - 如何根据计数找到比例
- ios - iOS - 多播网络失败:“无法分配请求的地址”
- azure - 串行执行 ansible playbook 以升级到 azure vmss 的最新模型
- java - Spring:如何为所选端点设置网络连接超时?
- node.js - 重建一个 vuejs (nodejs) 模块
- python - XLWings 格式刷
- git - 更改 GIT LFS 存储目录路径
- c++ - 如何调用模板数组运算符重载函数?
- django - Django 管理员组权限和访问
- android - Google Play 控制台中的 VALIDATE_APP_MESSAGE_TOO_MANY_LISTS_IN_TRACK 错误