当 Django 在 postgresql 中使用可序列化事务隔离级别时,哪些特定异常表示序列化失败?
What specific exceptions represent a serialization failure when Django is using serializable transaction isolation level with postgresql?
有时需要为 Django 中的数据库操作使用比默认 "read committed" 更高的隔离级别。 The docs warn 那:
Under higher isolation levels, your application should be prepared to handle exceptions raised on serialization failures.
但哪些特定异常表示序列化失败,与查询或事务的其他问题相比?
序列化失败后的简单重试机制可能如下所示:
for retries in range(0, 3):
try:
with transaction.atomic():
MyModel.objects.update(foo='bar')
except StuffHappened:
continue
else:
break
哪些特定异常应该替换 StuffHappened
以便只有序列化失败而不是其他异常导致重试?
Django 有多种Database Exceptions and Transaction Exceptions。 one/some 可能表示序列化失败?
为此我对 postgresql 特别感兴趣。
嗯,问得好。该文档暗示适当的例外是 TransactionManagementError
:
TransactionManagementError
is raised for any and all problems related to database transactions.
然而,source code 给出了一个强有力的线索,表明它不是:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
请注意,这是一个ProgrammingError
,它确实用于指示程序员错误(即"used improperly")。
如果我们查看 psycopg(用于 PostgreSQL 支持的 Python 适配器)的文档,我们会发现它会引发 psycopg2.extensions.TransactionRollbackError
:
exception psycopg2.extensions.TransactionRollbackError
(subclasses OperationalError
)
Error causing transaction rollback (deadlocks, serialization failures, etc).
但是 Django 用它做什么呢?好吧,作为 documented here,它将标准 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
确实是处理事务问题的正确异常类型,因此捕获它有望成为一个相当有效的数据库-不可知的解决方案。
有时需要为 Django 中的数据库操作使用比默认 "read committed" 更高的隔离级别。 The docs warn 那:
Under higher isolation levels, your application should be prepared to handle exceptions raised on serialization failures.
但哪些特定异常表示序列化失败,与查询或事务的其他问题相比?
序列化失败后的简单重试机制可能如下所示:
for retries in range(0, 3):
try:
with transaction.atomic():
MyModel.objects.update(foo='bar')
except StuffHappened:
continue
else:
break
哪些特定异常应该替换 StuffHappened
以便只有序列化失败而不是其他异常导致重试?
Django 有多种Database Exceptions and Transaction Exceptions。 one/some 可能表示序列化失败?
为此我对 postgresql 特别感兴趣。
嗯,问得好。该文档暗示适当的例外是 TransactionManagementError
:
TransactionManagementError
is raised for any and all problems related to database transactions.
然而,source code 给出了一个强有力的线索,表明它不是:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
请注意,这是一个ProgrammingError
,它确实用于指示程序员错误(即"used improperly")。
如果我们查看 psycopg(用于 PostgreSQL 支持的 Python 适配器)的文档,我们会发现它会引发 psycopg2.extensions.TransactionRollbackError
:
exception
psycopg2.extensions.TransactionRollbackError
(subclassesOperationalError
)Error causing transaction rollback (deadlocks, serialization failures, etc).
但是 Django 用它做什么呢?好吧,作为 documented here,它将标准 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
确实是处理事务问题的正确异常类型,因此捕获它有望成为一个相当有效的数据库-不可知的解决方案。