我在Django中使用带有mysql数据库的innoDB表。在调查错误期间
OperationalError:(1213,'尝试获取锁定时发现死锁;尝试重启事务')
我从this answer发现了Omry。在答案的最后部分,他建议
客户端应自动重试。
我试图将这个逻辑放在代码中,但同时在django中可以直接使用任何钩子。这样我们就可以设置3次自动重试,以防死锁。此外,如果有人可以举例说明将这个逻辑放在代码中(我使用的是django过滤器)。
PS:我可以在Omry的答案下面问这个问题,但我低于50分并想把它带给django专家。答案 0 :(得分:7)
这是一个老问题,但由于没有人发布答案,所以就是这样。
为了在发生死锁时重试查询,我所做的就是修补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(死锁)的OperationalError,它将等待200毫秒并再次尝试。它将执行此操作3次,如果3次后问题仍未解决,则会引发原始异常。
当django项目被加载到内存中时,应该执行此代码,因此放置它的好地方是在任何应用程序的__init__.py
文件中(我放在__init__.py
文件中我的项目的主目录 - 与你的django项目同名的那个。)
希望这有助于将来的任何人。