在django和mysql设置中死锁后,Hook可用于自动重试

raj*_*kan 5 mysql django mysql-python

我在Django中使用innoDB表和mysql数据库.在调查错误期间

OperationalError:(1213,'尝试获取锁时发现死锁;尝试重启事务')

我从Omry那里得到了这个答案.他建议在答案的最后部分

客户端应自动重试.

我试图将这个逻辑放在代码中,但同时在django中可以直接使用任何钩子.这样我们就可以设置3次自动重试,以防死锁.此外,如果有人可以举例说明将这个逻辑放在代码中(我使用的是django过滤器).

PS:我可以在Omry的答案下面问这个问题,但我低于50分并想把它带给django专家.

Luc*_*rea 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
Run Code Online (Sandbox Code Playgroud)

上面的代码是:它将尝试运行查询,如果抛出ErrorError并返回错误代码1213(死锁),它将等待200 ms并再次尝试.它将执行此操作3次,如果3次后问题仍未解决,则会引发原始异常.

当django项目被加载到内存中时,应该执行此代码,因此放置它的好地方是在__init__.py任何应用程序的__init__.py文件中(我放在项目主目录的文件中 - 具有相同名称的文件)作为你的django项目).

希望这对未来的任何人都有帮助.