Как сохранить соединение с базой данных на веб-сервере python
Я смотрю учебник Flask, и он предлагает создать новое соединение с базой данных для каждого веб-запроса. Правильно ли это? Я всегда думал, что соединение с базой данных должно быть создано только один раз для каждого потока. Это можно сделать, поддерживая приложение как поточно-безопасное, с флягой или другими веб-серверами python.
Ответы
Ответ 1
Для учебных целей возможно да. Но в реальном приложении, работающем на производственной среде, которая не является идеальной ситуацией вообще.
Обычно вы всегда хотите иметь пул соединений между вашим приложением и базой данных. Независимо от того, какой язык/база данных вы используете, это общее решение.
Пул соединений с базой данных поддерживает открытие нескольких соединений. Уровень приложения просто использует соединение, которое не используется, соединения освобождаются, когда прикладной уровень им больше не нужен. Под "выпуском" я подразумеваю, что они возвращаются в пул, чтобы снова использоваться.
Нижняя строка, соединения не открываются/закрываются за запрос. Они получают/освобождаются из/в пул соединений с базой данных.
Например, с Python и mysql вы можете перейти PySQLPool.
Ответ 2
Создает новое соединение каждый запрос, как идти? Нет. Для больших приложений мы настоятельно рекомендуем использовать SQLAlchemy (у которого может быть настроен пул подключений), даже если вы не заинтересованы в ORM. Фактически в документах есть раздел: http://flask.pocoo.org/docs/patterns/sqlalchemy/#sql-abstraction-layer
Ответ 3
Вот хорошее сравнение производительности с различными решениями. (PostgreSQL)
Краткая версия:
Посмотрите на pgBouncer
Длинная версия:
http://www.askthepony.com/blog/2011/07/django-and-postgresql-improving-the-performance-with-no-effort-and-no-code/
Ответ 4
По моему опыту, часто бывает неплохо закрывать соединения часто. В частности, MySQL любит закрывать те соединения, которые простаивали какое-то время, и иногда это может оставить постоянное соединение в устаревшем состоянии, которое может сделать приложение невосприимчивым.
То, что вы действительно хотите сделать, - это оптимизировать "мертвое время соединения", долю времени соединения, но не выполняет никакой работы. В случае создания нового соединения с каждым запросом это мертвое время - это просто время установки и разрыва. Если вы только подключаетесь один раз (за поток), и это никогда не ухудшается, то мертвое время - это время простоя.
Когда ваше приложение обслуживает только несколько запросов, количество подключаемых соединений также будет небольшим, и поэтому не так много преимуществ, связанных с открытием соединения, но бездействия. С другой стороны, когда приложение очень занято, соединения почти никогда не работают, и закрытие соединения, которое будет немедленно открыто, также будет потрачено впустую. В середине, когда новые запросы иногда следуют в запросах на полеты, но иногда их нет, вам нужно будет выполнить некоторую настройку производительности на такие вещи, как размер пула, тайм-аут запроса и т.д.
Очень занятое приложение, использующее пул соединений для открытия соединений, будет видеть только один вид мертвого времени; ожидая запросов, которые никогда не вернутся, потому что соединение ухудшилось. Простое решение этой проблемы - выполнить известный, хороший запрос (который в MySQL пишется SELECT 1
), прежде чем предоставлять соединение из пула в запрос и переработать соединение, если оно не вернется быстро.