Избежание «сервера MySQL ушел» на редко используемом сервере Python / Flask с SQLAlchemy - PullRequest
46 голосов
/ 24 июня 2011

Как настроить Flask / SQLAlchemy для создания нового подключения к базе данных, если оно отсутствует?

У меня есть нечасто посещаемый сервер Python / Flask, который использует SQLAlchemy. Его посещают каждые пару дней, и при первом посещении он часто выдает ошибку «Сервер MySQL ушел». Последующие просмотры страниц - это нормально, но эта первоначальная ошибка выглядит непрофессионально.

Я бы хотел знать правильный способ справиться с этим - такой совет, как «сделать действительно длительный перерыв», который в этом случае длился бы около 4 дней, кажется неправильным. Как я могу проверить отсутствие соединения с базой данных и создать его при необходимости?

Ответы [ 6 ]

48 голосов
/ 25 июня 2011

У меня были проблемы с этим раньше, и я обнаружил, что способ справиться с этим - не проводить сессии.Проблема в том, что вы пытаетесь держать соединение открытым слишком долго.Вместо этого используйте сеанс локальной области потока, например, в __init__.py или в пакете утилит, который вы импортируете повсюду:

from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session( sessionmaker() )

Затем настройте ваши движки и метаданные один раз.Это позволяет пропускать механику конфигурации при каждом подключении / отключении.После этого вы можете выполнить свою работу с БД следующим образом:

session = Session()
someObject = session.query( someMappedClass ).get( someId )
# use session like normal ...
session.close()

Если вы хотите сохранить старые объекты и не хотите оставлять сеанс открытым, то вы можете использовать приведенный выше шаблон иповторно используйте старые объекты, например:

session = Session()
someObject = session.merge( someObject )
# more db stuff
session.close()

Дело в том, что вы хотите открыть сеанс, выполнить свою работу, а затем закрыть сеанс.Это очень хорошо позволяет избежать тайм-аутов.Существует множество опций для .merge и .add, которые позволяют вам включать изменения, сделанные вами в отдельные объекты, или загружать новые данные из БД.Документы очень многословны, но как только вы поймете, что ищете, вам будет немного легче найти.

Чтобы действительно пройти весь путь и предотвратить «уход» MySQL, вам нужнорешите проблему вашего пула соединений, сохраняя соединения открытыми слишком долго и проверяя старое соединение для вас.

Чтобы установить новое соединение, вы можете установить опцию pool_recycle в своем вызове create_engine.Задайте в этом параметре pool_recycle количество секунд времени в пуле соединений между извлечениями, которые вы хотите создать вместо нового существующего соединения.

24 голосов
/ 06 марта 2016

У меня была похожая проблема, но я получал ошибку «MySQL исчезла» где-то между 5 минутами и 2 часами каждого сеанса.

Я использую Flask-SQLAlchemy, поэтому предполагается, что он закрывает незанятые соединения, но, похоже, этого не происходит, если соединение не было в течение нескольких часов.

В конце концовЯ сузил его до следующих настроек Flask-SQLAlchemy:

app.config['SQLALCHEMY_POOL_SIZE'] = 100
app.config['SQLALCHEMY_POOL_RECYCLE'] = 280

По умолчанию для них установлены значения 10 и 7200 (2 часа) соответственно.

Это вопрос игры с этиминастройки, чтобы соответствовать вашей среде.

Например, во многих местах я читал, что SQLALCHEMY_POOL_RECYCLE должен быть установлен на 3600, но это не сработало для меня.Я хостинг с PythonAnywhere, и они убивают простоя подключения MySQL через 5 минут (300 секунд).Таким образом, установка моего значения менее 300 решила проблему.

Я надеюсь, что это поможет другим, потому что я потратил слишком много времени на эту проблему.

http://flask -sqlalchemy.pocoo.org / 2.1 / config / # configuration-keys

17 голосов
/ 13 июля 2017

2018 ответ: В SQLAlchemy v1.2.0 + у вас есть функция pre-ping пула соединений , доступная для решения этой проблемы «сервер MySQL исчез».

Предварительная проверка пула подключений - теперь в пул подключений включена дополнительная функция «предварительная проверка связи», которая будет проверять «живучесть» пулированного соединения для каждой проверки соединения, прозрачно перерабатывая соединение DBAPI, если база данныхотсоединен.Эта функция устраняет необходимость использования флага «перезапуск пула», а также проблему ошибок, возникающих при использовании соединения в пуле после перезапуска базы данных.

Пессимистическое тестирование соединений при извлечении возможно сновый аргумент:

engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
6 голосов
/ 20 января 2013

ЕСЛИ вы используете Flask-SQLAlchemy:

Похоже, что доступно исправление: https://github.com/mitsuhiko/flask-sqlalchemy/issues/2

К сожалению, установка по умолчанию (pip install flask-sqlalchemy) не применяетсяисправление еще, особенно в этом вопросе: https://github.com/e-dard/flask-sqlalchemy/commit/cf659f346e005d34257d256fa4c42889741fc31f

Получение последней версии от github должно исправить это.

1 голос
/ 25 июня 2018

Когда я столкнулся с этой ошибкой, я сохранял изображение размером LONGBLOB / LargeBinary размером ~ 1 МБ.Мне пришлось настроить параметр конфигурации max_allowed_packet в MySQL.

Я использовал mysqld --max-allowed-packet=16M

0 голосов
/ 03 мая 2019

Если вы используете Pool, вы должны установить recyle меньше, чем wait_timeout DB wait_timeout равно 60. Поэтому я установил 40 для повторного использования

from sqlalchemy.pool import Pool
pool.QueuePool(self.get_connection, max_overflow=0,pool_size=40,recycle=50)
...