我在 Django 中使用 innoDB 表和 mysql 数据库。在调查错误期间
操作错误:(1213,“尝试获取锁定时发现死锁;尝试重新启动事务”)
我碰到这个答案 https://stackoverflow.com/a/2423921/1026861 from Omry https://stackoverflow.com/users/1930838/omry-yadan。在答案的最后部分他建议
客户端应该自动重试。
我试图将这个逻辑放入代码中,但同时 django 中是否有直接可用的钩子。这样我们就可以设置3次自动重试,以防死锁。另外,如果有人可以给出将此逻辑放入代码中的示例(我正在使用 django 过滤器)。
PS:我本可以在 Omry 的答案下面问这个问题,但我低于 50 分,也想把它带给 django 专家。
这是一个老问题,但由于没有人发布答案,所以就在这里。
为了在发生死锁时重试查询,我所做的是对 django 的 CursorWrapper 类的“execute”方法进行了猴子修补。每当进行查询时都会调用此方法,因此它将在整个 ORM 中工作,并且您不必担心项目中的死锁:
import django.db.backends.utils
from django.db import OperationalError
import time
original = django.db.backends.utils.CursorWrapper.execute
def execute_wrapper(*args, **kwargs):
attempts = 0
while attempts < 3:
try:
return original(*args, **kwargs)
except OperationalError as e:
code = e.args[0]
if attempts == 2 or code != 1213:
raise e
attempts += 1
time.sleep(0.2)
django.db.backends.utils.CursorWrapper.execute = execute_wrapper
上面的代码的作用是:它将尝试运行查询,如果抛出一个操作错误,错误代码为 1213(死锁),它将等待 200 毫秒,然后重试。它将执行 3 次,如果 3 次后问题仍未解决,则引发原始异常。
该代码应该在 django 项目加载到内存中时执行,因此最好将其放在__init__.py
您的任何应用程序的文件(我放置在__init__.py
我的项目主目录的文件 - 与您的 django 项目同名的文件)。
希望这对将来的任何人都有帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)