Крюк доступен для автоматической повторной попытки после тупика в настройках django и mysql

Я использую таблицу innoDB в Django с базой данных MySQL. Во время расследования ошибки

Операционная ошибка: (1213, 'Обнаружен тупик при попытке получить блокировку; попробуйте перезапустить транзакцию ')

Я наткнулсяэтот ответ отOmry, В последней части ответа он предлагает

клиент должен повторить попытку автоматически.

Я пытаюсь поместить эту логику в код, но в то же время есть ли доступный хук напрямую в django. Так что мы можем установить 3-х кратный автоматизированный повтор в случае тупика. Также, если кто-нибудь может привести пример размещения этой логики в коде (м с использованием фильтров Django).

PS: я мог бы спросить это ниже Omry 'ответ, но ям ниже 50 баллов, а также хотел довести это до экспертов django.

 Timmy O'Mahony19 июн. 2013 г., 11:05
Какой код вы выполняете и где он находится в вашем проекте django?
 rajalokan20 июн. 2013 г., 11:04
Привет, Тимми, спасибо, что заглянул. Я использую django_auth_ldap для синхронизации моего сервера LDAP с моей базой данных. Во время одного из вызовов manage_user (для создания / удаления / обновления информации о пользователе) я делаю ldap_backend.populate_user (<адрес электронной почты>) [это синхронизировать все группы LDAP с django auth_user_groups]. Это заставляет MySQL зайти в тупик.

Ответы на вопрос(1)

Это старый вопрос, но так как никто не опубликовал ответ, вот он.

Чтобы повторить запросы в случае возникновения тупика, я сделал, чтобы я исправил метод "выполнить» ДжангоКласс CursorWrapper. Этот метод вызывается всякий раз, когда делается запрос, поэтому он будет работать по всему 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

Код, приведенный выше: попытается выполнить запрос, и если выдается сообщение OperationalError с кодом ошибки 1213 (взаимоблокировка), он будет ждать 200 мс и повторять попытку. Он будет делать это 3 раза, и если после 3 раз проблема не будет решена, возникает оригинальное исключение.

Этот код должен выполняться, когда проект django загружается в память, поэтому хорошее место для его размещения - это__init__.py файл любого из ваших приложений (я поместил в__init__.py файл моего проектаs главный каталог - тот, который имеет то же имя, что и ваш проект django).

Надеюсь, это поможет кому-нибудь в будущем.

 acidjunk23 мая 2018 г., 14:42
Интересно, безопасно ли это использовать с транзакциями?
 Murthy24 нояб. 2018 г., 15:14
Да. Это решение работает нормально. Теперь мы видим следующую ошибку. Операционная ошибка: (1305, 'SAVEPOINT s139806324311104_x9 не существует '). Моя транзакция атомарна в моем views.py. Может кто-нибудь помочь решить эту проблему?
 Marcos Dione27 нояб. 2017 г., 15:17
Большое спасибо, яя использую что-то подобное, чтобы исправитьOperationalError: (2006, 'MySQL server has gone away')Но вместо того, чтобы делать свой собственный код упаковки, ям с помощью:retry

Ваш ответ на вопрос