Повторное подключение MySQL по таймауту
у меня есть программа Python, которая работает на фоне в течение нескольких недель, и делает запросы к базе данных время от времени. Для этого я использую ORM peewee
(версия 2.2.1). Я использую MySQL
в качестве бэкэнда.
в последнее время я столкнулся с повторяющейся проблемой с доступом к БД, обычно после нескольких дней запуска программы. Ошибка, вызванная peewee
и
peewee.OperationalError: (2006, 'MySQL server has gone away')
traceback глубоко в peewee
. Я размещаю его здесь, но как мой virtualenv
делает имена файлов слишком длинными, я сокращаю их:
File ".../local/lib/python2.7/site-packages/peewee.py", line 2910, in save
ret_pk = self.insert(**field_dict).execute()
File ".../local/lib/python2.7/site-packages/peewee.py", line 2068, in execute
return self.database.last_insert_id(self._execute(), self.model_class)
File ".../local/lib/python2.7/site-packages/peewee.py", line 1698, in _execute
return self.database.execute_sql(sql, params, self.require_commit)
File ".../local/lib/python2.7/site-packages/peewee.py", line 2232, in execute_sql
self.commit()
File ".../local/lib/python2.7/site-packages/peewee.py", line 2104, in __exit__
reraise(new_type, new_type(*exc_value.args), traceback)
File ".../local/lib/python2.7/site-packages/peewee.py", line 2223, in execute_sql
res = cursor.execute(sql, params or ())
File ".../local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 205, in execute
self.errorhandler(self, exc, value)
File ".../local/lib/python2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
peewee.OperationalError: (2006, 'MySQL server has gone away')
возможные попытки решения, которые я нашел:
- на этот вопрос, один из комментариев предлагает пинговать
MySQL
сервер время от времени, чтобы сохранить его (соединение?) живой. Однако я не уверен, как это сделать через ORM. (должен ли я простоSELECT 1
каждый час, скажем?) - на этот выпуск GitHub peewee, который был открыт 4 месяца назад та же ошибка упоминается, хотя там утверждается, что она решена (и я использую более новую версию).
- на 7-летний выпуск of
trac
, одно предложение-увеличить тайм-аутMySQL
в течение 3 дней. - в этой форум параметр увеличения
MySQL
предлагается тайм-аут, но предлагается альтернатива "использование опции autoReconnect для MySQL JDBC connector". Я попытался выяснить, если такой опция существует для PythonMySQLdb
модуль, но не смог найти. - и справочная страница MySQL о поведении повторного подключения, но это немного сложно для моего понимания
MySQL
(обычно я работаю только с ORMs), и я не знаю, как применить любой из них изpeewee
.
даже если я могу пинговать базу данных, чтобы сохранить соединение живым в течение более длительных периодов, я думаю, что это считается плохой практикой, чтобы сохранить соединение живым когда в этом нет необходимости. Есть ли способ снова открыть соединение через ORM? Я рассматриваю как pinging, так и увеличение тайм-аута MySQL
как обходные пути, в то время как реальным решением было бы снова подключиться, когда это необходимо (и реальное решение-это то, что я прошу).
3 ответов
вы должны поймать исключение и на основании которых ошибки, восстановить или сделать что-то еще. Является ли это тайм-аут соединения, или сетевая проблема, или MySQL должен быть перезапущен.
приведенный ниже (псевдоиш) код показывает, как вы могли бы это сделать, но это еще не все. Вы захотите попробовать несколько раз, а затем выйти из игры или, возможно, попробовать каждые 2 минуты или около того.
while True:
try:
# do your database stuff
except peewee.OperationalError as exc:
# Oops! We have to try to reconnect
на самом деле не имеет значения, используете ли вы ORM или нет. Однако ORM может предложить это функциональность.
у меня была та же проблема, и для peewee с помощью MySQLdb я получил следующее решение при инициализации экземпляра базы данных MySQL:
db = MySQLDatabase(db_name, user=db_username, passwd=db_password, host=db_host, port=db_port)
db.get_conn().ping(True)
где для функции ping есть:
проверяет, работает ли соединение с сервером. Если это пошел вниз, предпринята попытка автоматического повторного подключения.
эта функция может использоваться клиентами, которые остаются без дела в течение длительного времени while, чтобы проверить, закрыт ли сервер соединение и при необходимости подключитесь заново.
New в 1.2.2: принимает необязательный параметр повторного подключения. Если это правда, то клиент попытается восстановить соединение. Обратите внимание, что этот параметр настойчивый. По умолчанию, это в MySQL
нестандартные. Вы должны предположить, что ping () выполняет неявное откат; используется только при запуске новой транзакции. Вы были предупрежденный.
на db.get_conn().ping.__doc__
. Виду, что db.get_conn().ping(True)
должен использоваться, если вы снова создадите другое соединение. Поэтому, если вы снова подключитесь (через db.connect()
например), вы должны повторить пинг.
я решил эту проблему.
мое решение - использовать MySQL connection pool PooledMySQLDatabase
С playhouse.pool
модуль.
читайте: https://github.com/coleifer/peewee/issues/239
from peewee import *
from playhouse.pool import *