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

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

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

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

Какое самое лучшее решение для "снижения", чтобы переключить это на использование пула соединений в python? Я представляю себе что-то вроде решения DBCP для Java.

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

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

4b9b3361

Ответ 1

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

Мне кажется, что ORM более популярны, чем "сырые" SQL-соединения. Зачем? Поскольку Python является OO, и отображение из строки SQL в объект абсолютно необходимо. Существует не так много случаев, когда вы имеете дело со строками SQL, которые не сопоставляются с объектами Python.

Я думаю, что SQLAlchemy или SQLObject (и связанный с ним пул соединений) более идиоматическое решение Pythonic.

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

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

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

Ответ 2

В MySQL?

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

Ответ 6

Создание собственного пула подключений - идея BAD, если ваше приложение когда-либо решает начать многопоточность. Создание пула соединений для многопоточного приложения намного сложнее, чем одно для однопоточного приложения. В этом случае вы можете использовать что-то вроде PySQLPool.

Это также идея BAD для использования ORM, если вы ищете производительность.

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

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

Ответ 7

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

Вы можете проверить их:

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

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

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()

Ответ 8

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

pip install DBUtils

Ответ 9

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

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

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