Какое лучшее решение для пула соединений с базой данных в Python? - PullRequest
32 голосов
/ 19 сентября 2008

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

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

Какое наилучшее решение «drop in» для переключения на использование пула соединений в python? Я представляю что-то вроде решения DBCP для Java.

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

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

Ответы [ 8 ]

22 голосов
/ 19 сентября 2008

В MySQL?

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

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

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

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

16 голосов
/ 19 сентября 2008

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

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

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

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

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

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

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

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

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

import sqlalchemy.pool as pool
import MySQLdb as mysql
mysql = pool.manage(mysql)
6 голосов
/ 14 июля 2014

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

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

2 голосов
/ 23 августа 2011

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

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

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

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

2 голосов
/ 14 мая 2009

Я просто искал то же самое.

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

1 голос
/ 10 июня 2017

Отвечая на старый поток, но в последний раз, когда я проверял, 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()
0 голосов
/ 11 ноября 2018

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

pip install DBUtils

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...