use*_*461 4 django postgresql transactions exception-handling isolation-level
有时需要对 Django 中的数据库操作使用比默认的“已提交读”更高的隔离级别。 文档警告说:
在更高的隔离级别下,您的应用程序应该准备好处理因序列化失败而引发的异常。
但是哪些特定的异常表示序列化失败,而不是查询或事务的一些其他问题?
序列化失败后的简单重试机制可能如下所示:
for retries in range(0, 3):
try:
with transaction.atomic():
MyModel.objects.update(foo='bar')
except StuffHappened:
continue
else:
break
Run Code Online (Sandbox Code Playgroud)
应该替换哪些特定异常,StuffHappened以便只有序列化失败而不是其他异常会导致重试?
Django 有多种数据库异常和事务异常。其中一个/一些可能代表序列化失败?
为此,我对 postgresql 特别感兴趣。
嗯,好问题。该文档暗示适当的例外将是TransactionManagementError:
TransactionManagementError是针对与数据库事务相关的任何和所有问题提出的。
但是,源代码提供了一个强有力的线索,它不是:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
Run Code Online (Sandbox Code Playgroud)
请注意,这是一个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
Run Code Online (Sandbox Code Playgroud)
根据 PostgreSQL 公开的错误详细信息(可通过 获得e.__cause__.diag),可能会编写更具体的测试。
不过,通常情况下,Python DB API 2.0 文档指出这OperationalError确实是事务问题的正确异常类型,因此捕获它有望成为一种合理有效的与数据库无关的解决方案。
| 归档时间: |
|
| 查看次数: |
982 次 |
| 最近记录: |