嗯,好问题。该文档暗示适当的例外是TransactionManagementError https://docs.djangoproject.com/en/2.1/ref/exceptions/#transactionmanagementerror:
TransactionManagementError
针对与数据库事务相关的任何和所有问题而提出。
但是,那源代码 https://github.com/django/django/blob/2.1/django/db/transaction.py#L8给出了一个强有力的线索,表明它不是:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
请注意,这是一个ProgrammingError https://www.python.org/dev/peps/pep-0249/#programmingerror,这确实用于指示程序员错误(即“使用不当”)。
如果我们查看 psycopg(用于 PostgreSQL 支持的 Python 适配器)的文档,我们会发现它会引发psycopg2.extensions.TransactionRollbackError http://initd.org/psycopg/docs/extensions.html#psycopg2.extensions.TransactionRollbackError:
例外psycopg2.extensions.TransactionRollbackError
(子类OperationalError
)
导致事务回滚的错误(死锁、序列化失败等)。
但 Django 会用它做什么呢?以及记录在这里 https://docs.djangoproject.com/en/dev/ref/exceptions/#database-exceptions,它将标准 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 http://initd.org/psycopg/docs/extensions.html#psycopg2.extensions.Diagnostics)也许可以编写更具体的测试。
不过,一般来说,Python DB API 2.0 文档指出OperationalError https://www.python.org/dev/peps/pep-0249/#operationalerror确实是事务问题的正确异常类型,因此捕获该异常类型有望成为一个相当有效的与数据库无关的解决方案。