Подтвердить что ты не робот

Избегание "сервера MySQL ушло" на редко используемом сервере Python/Flask с SQLAlchemy

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

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

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

4b9b3361

Ответ 1

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

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

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

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, которые позволяют либо включать изменения, внесенные вами в отдельные объекты, либо загружать новые данные из db. Документы очень подробные, но как только вы знаете, что вы ищете, это может быть немного легче найти.

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

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

Ответ 2

У меня была похожая проблема, но для меня я получал ошибку "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

ОБНОВЛЕНИЕ: 2019-ОКТ-08

Ключи конфигурации 'SQLALCHEMY_POOL_SIZE' и 'SQLALCHEMY_POOL_RECYCLE' устарели с версии 2.4 и будут удалены в версии 3.0 SQLAlchemy. Используйте 'SQLALCHEMY_ENGINE_OPTIONS', чтобы установить соответствующие значения.

app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'pool_size' : 100, 'pool_recycle' : 280}

Ответ 3

Ответ 2018: в SQLAlchemy v1.2. 0+ у вас есть функция предварительной проверки пула соединений для решения этой проблемы "сервер MySQL исчез".

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

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

engine = create_engine("mysql+pymysql://user:[email protected]/db", pool_pre_ping=True)

Ответ 4

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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