Django - OperationalError: (2006, "сервер MySQL ушел" )

В нижней строке: Как вы обновляете соединение MySQL в django?

После ошибки MySQL server has gone away я обнаружил, что документация по MySQL и другие источники (здесь) предлагают увеличить параметр wait_timeout MySQL. Для меня это похоже на обходное решение, а не на решение. Я бы предпочел сохранить разумный wait_timeout и обновить соединение в коде.

Ошибка:

  File "C:\my_proj\db_conduit.py", line 147, in load_some_model
    SomeModel.objects.update()
  File "C:\Python26\lib\site-packages\django-1.3-py2.6.egg\django\db\models\manager.py", line 177, in update
    return self.get_query_set().update(*args, **kwargs)
  File "C:\Python26\lib\site-packages\django-1.3-py2.6.egg\django\db\models\query.py", line 469, in update
    transaction.commit(using=self.db)
  File "C:\Python26\lib\site-packages\django-1.3-py2.6.egg\django\db\transaction.py", line 142, in commit
    connection.commit()
  File "C:\Python26\lib\site-packages\django-1.3-py2.6.egg\django\db\backends\__init__.py", line 201, in commit
    self._commit()
  File "C:\Python26\lib\site-packages\django-1.3-py2.6.egg\django\db\backends\__init__.py", line 46, in _commit
    return self.connection.commit()
OperationalError: (2006, 'MySQL server has gone away')

Настройка: Django 1.3.0, MySQL 5.5.14, innodb 1.1.8, Python 2.6.6, Win7 64bit

Ответ 1

с той же проблемой. Мне нужна идея, как проверить состояние соединения для подключения MySQLdb в django. я думаю, это может быть достигнуто

try:
    cursor.execute(sql)
catch OperationalError:
    reconnect

кто-нибудь лучше знает?

UPDATE

мое решение

self.connection.stat()
if self.connection.errno()!=0:

проверить состояние соединения mysqldb, если ошибка воссоздает соединение

UPDATE AGAIN

вам также нужно обслуживать случай, если соединение близко

if self.connection.open:
    self.connection.stat()

соединение обновления просто воссоздает его

    db_settings = settings.DATABASES['mysql_db']
    try:
        self.connection = MySQLdb.connect(host=db_settings['HOST'],port=int(db_settings['PORT']),db=db_settings['NAME'],user=db_settings['USER'],passwd=db_settings['PASSWORD'])
    except MySQLdb.OperationalError, e:
        self.connection = None

Ответ 2

Идея решения понятна: подключитесь к mysql, если текущее соединение нарушено.

Пожалуйста, проверьте это:

def make_sure_mysql_usable():
    from django.db import connection, connections
    # mysql is lazily connected to in django.
    # connection.connection is None means
    # you have not connected to mysql before
    if connection.connection and not connection.is_usable():
        # destroy the default mysql connection
        # after this line, when you use ORM methods
        # django will reconnect to the default mysql
        del connections._connections.default

Ответ 3

Начиная с Django 1.6, вы можете использовать

import django.db

django.db.close_old_connections()

Это в основном то же самое, что и ответ adamsmith, за исключением того, что он обрабатывает несколько баз данных, а также CONN_MAX_AGE настройку CONN_MAX_AGE. Django вызывает close_old_connections() автоматически до и после каждого запроса, поэтому вам, как правило, не нужно беспокоиться об этом, если у вас нет какого-либо долгосрочного кода вне обычного цикла запрос/ответ.

Ответ 4

Основная причина, которая приводит к этому исключению, в основном из-за того, что клиент идеален дольше, чем wait_timeout на сервере MySQL.

Для предотвращения такого рода ошибок django поддерживает опцию с именем CONN_MAX_AGE которая позволяет django воссоздавать новое соединение, если старые соединения идеальны слишком долго. Поэтому вы должны убедиться, что значение CONN_MAX_AGE меньше значения wait_timout.

Одна важная вещь состоит в том, django с wsgi ручками проверки CONN_MAX_AGE каждые запросы от вызова close_old_connections. Так что в основном вам не нужно заботиться об этом. Однако, если вы используете django в стандартном приложении, нет триггера для запуска этой функции. Таким образом, вы должны вызвать его вручную. Так что давайте вызовем close_old_connections в вашей кодовой базе.

Примечание: close_old_connections сохранит старые соединения, если они еще не истекли. Ваши соединения все еще используются повторно в случае высокочастотного запроса.