Какое лучшее решение для пула подключений к базе данных в Python?

StackOverflow https://stackoverflow.com/questions/98687

Вопрос

Я разработал несколько пользовательских классов, подобных DAO, для удовлетворения некоторых очень специализированных требований моего проекта, который представляет собой серверный процесс, который не выполняется внутри какой-либо инфраструктуры.

Решение работает отлично, за исключением того, что каждый раз, когда делается новый запрос, я открываю новое соединение через MySQLdb.connect.

Какое решение лучше всего использовать для переключения на использование пула соединений в Python?Я представляю себе что-то вроде общего решения DBCP для Java.

Процесс выполняется долго и имеет множество потоков, которым необходимо отправлять запросы, но не все одновременно...в частности, они проделывают довольно много работы, прежде чем короткими порциями записать часть своих результатов.

Отредактировано, чтобы добавить:После еще нескольких поисков я нашел anitpool.py это выглядит прилично, но, поскольку я относительно новичок в Python, думаю, я просто хочу убедиться, что не упускаю более очевидного/более идиоматического/лучшего решения.

Это было полезно?

Решение

IMO, «более очевидное/более идиоматичное/лучшее решение» — использовать существующий ORM, а не изобретать DAO-подобные классы.

Мне кажется, что ORM более популярны, чем «необработанные» SQL-соединения.Почему?Потому что Питон является OO и сопоставление строки SQL с объектом является абсолютно необходимо.Не так уж много случаев, когда вы имеете дело со строками SQL, которые не сопоставляются с объектами Python.

я думаю что SQLАлхимия или SQLОбъект (и связанный с ним пул соединений) является более идиоматическим решением Pythonic.

Объединение в пулы как отдельная функция не очень распространено, поскольку чистый SQL (без сопоставления объектов) не очень популярен для сложных, длительных процессов, которые выигрывают от объединения в пул соединений.Да, чистый SQL является используется, но он всегда используется в более простых или более контролируемых приложениях, где объединение в пул бесполезно.

Я думаю, у вас может быть два варианта:

  1. Пересмотрите свои классы, чтобы использовать SQLAlchemy или SQLObject.Хотя на первый взгляд это кажется болезненным [вся эта работа потрачена впустую], вы должны быть в состоянии использовать весь дизайн и мысли, и это всего лишь упражнение по принятию широко используемого решения ORM и пула.
  2. Создайте свой собственный простой пул соединений, используя описанный вами алгоритм — простой набор или список соединений, которые вы циклически перебираете.

Другие советы

В MySQL?

Я бы сказал, не беспокойтесь о пуле соединений.Они часто являются источником проблем, и в случае с MySQL они не дадут вам того преимущества в производительности, на которое вы надеетесь.Идти по этому пути, возможно, придется приложить немало усилий – с политической точки зрения – потому что в этой области так много лучших практик, маханий руками и пустословия из учебников о преимуществах пула соединений.

Пулы соединений — это просто мост между поствеб-эрой приложений без сохранения состояния (например,протокол HTTP) и довеб-эру долгоживущих приложений пакетной обработки с отслеживанием состояния.Поскольку соединения были очень дорогими в базах данных до появления Интернета (поскольку никто не заботился слишком много о том, сколько времени требуется для установления соединения), приложения пост-веб разработали эту схему пула соединений, чтобы каждое обращение не влекло за собой огромные накладные расходы на обработку. на СУРБД.

Поскольку MySQL — это скорее СУБД веб-эры, соединения чрезвычайно легкие и быстрые.Я написал множество веб-приложений большого объема, которые вообще не используют пул соединений для MySQL.

Это осложнение, от которого вы можете отказаться, если не возникнет политических препятствий, которые необходимо преодолеть.

Оберните свой класс соединения.

Установите ограничение на количество подключений.Вернуть неиспользуемое соединение.Перехватите близко, чтобы освободить соединение.

Обновлять:Я поместил что-то вроде этого в dbpool.py:

import sqlalchemy.pool as pool
import MySQLdb as mysql
mysql = pool.manage(mysql)

Старый поток, но для пула общего назначения (соединения или любой дорогой объект) я использую что-то вроде:

def pool(ctor, limit=None):
    local_pool = multiprocessing.Queue()
    n = multiprocesing.Value('i', 0)
    @contextlib.contextmanager
    def pooled(ctor=ctor, lpool=local_pool, n=n):
        # block iff at limit
        try: i = lpool.get(limit and n.value >= limit)
        except multiprocessing.queues.Empty:
            n.value += 1
            i = ctor()
        yield i
        lpool.put(i)
    return pooled

Который строится лениво, имеет необязательный предел и должен распространяться на любой вариант использования, который я могу придумать.Конечно, это предполагает, что вам действительно необходимо объединение любого ресурса в пул, чего не может быть во многих современных SQL-подобных системах.Использование:

# in main:
my_pool = pool(lambda: do_something())
# in thread:
with my_pool() as my_obj:
    my_obj.do_something()

Это предполагает, что любой объект, создаваемый ctor, при необходимости имеет соответствующий деструктор (некоторые серверы не уничтожают объекты соединения, если они не закрыты явно).

Я как раз искал нечто подобное.

Я нашел pysqlpool и модуль пула sqlalchemy

Создание собственного пула соединений — ПЛОХАЯ идея, если ваше приложение когда-нибудь решит начать использовать многопоточность.Создать пул соединений для многопоточного приложения гораздо сложнее, чем для однопоточного.В этом случае вы можете использовать что-то вроде PySQLPool.

Также ПЛОХАЯ идея использовать ORM, если вам нужна производительность.

Если вы будете иметь дело с огромными/тяжелыми базами данных, которые должны обрабатывать множество выбранных, вкладывает, обновляются и удаляются одновременно, тогда вам понадобится производительность, а это значит, что вам понадобится пользовательский SQL, написанный для оптимизации поисков и время блокировки.С ORM у вас обычно нет такой гибкости.

В общем, да, вы можете создать свой собственный пул соединений и использовать ORM, но только если вы уверены, что вам не понадобится ничего из того, что я только что описал.

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

Вы можете проверить их по адресу:

https://dev.mysql.com/doc/connector-python/en/connector-python-connection-pooling.html

Из TFA, если вы хотите явно открыть пул соединений (как заявил ОП):

dbconfig = {  "database": "test", "user":"joe" }
cnxpool = mysql.connector.pooling.MySQLConnectionPool(pool_name = "mypool",pool_size = 3, **dbconfig)

Доступ к этому пулу затем осуществляется путем запроса из пула через функцию get_connection().

cnx1 = cnxpool.get_connection()
cnx2 = cnxpool.get_connection()

Использовать DBUtils, простой и надежный.

pip install DBUtils
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top