在django和mysql设置中发生死锁后,挂钩可用于自动重试 [英] Hook available for automatic retry after deadlock in django and mysql setup

查看:272
本文介绍了在django和mysql设置中发生死锁后,挂钩可用于自动重试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using innoDB table in Django with mysql database. During investigation of error

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

OperationalError: (1213, 'Deadlock found when trying to get lock; try restarting transaction')

我从

I came across this answer from Omry. In last part of the answer he suggests

客户端应自动重试.

the client should retry automatically.

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

I am trying to put this logic in code but at the same time is there any hook directly available in django. So that we can set 3 time automate retry in case of deadlock. Also if anyone can give example of putting this logic in code (I'm using django filters).

PS:我本可以在Omry的回答下问这个问题,但我的得分低于50分,并且还想将其带给django专家.

PS: I could have asked this below Omry's answer but I'm below 50 points and also wanted to bring it to the django experts.

推荐答案

这是一个古老的问题,但是由于没有人发布答案,所以就在这里.

This is an old question but since nobody posted an answer, here it is.

为了重试是否发生死锁,我所做的是我修补了django的CursorWrapper类的方法"execute".每当进行查询时都会调用此方法,因此它将在整个ORM中都有效,并且您不必担心项目中的死锁:

In order to retry queries if a deadlock happens, what I did was I monkey patched the method "execute" of django's CursorWrapper class. This method is called whenever a query is made, so it will work across the entire ORM and you won't have to worry about deadlocks across your project:

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

以上代码的作用是:它将尝试运行查询,并且如果抛出错误代码为1313(死锁)的OperationalError,它将等待200 ms,然后重试.它将执行3次,如果3次之后问题仍未解决,则会引发原始异常.

What the code above does is: it will try running the query and if an OperationalError is thrown with the error code 1213 (a deadlock), it will wait for 200 ms and try again. It will do this 3 times and if after 3 times the problem was not solved, the original exception is raised.

此代码应在将django项目加载到内存中时执行,因此放置在任何应用程序的__init__.py文件中都是一个不错的地方(我放置在项目主程序的__init__.py文件中目录-与您的django项目同名的目录.

This code should be executed when the django project is being loaded into memory and so a good place to put it is in the __init__.py file of any of your apps (I placed in the __init__.py file of my project's main directory - the one that has the same name as your django project).

希望这对以后的所有人有帮助.

Hope this helps anyone in the future.

这篇关于在django和mysql设置中发生死锁后,挂钩可用于自动重试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆