Pergunta

Eu desenvolvi algum costume DAO-like classes para atender a alguns requisitos muito especializados para o meu projeto que é um processo do lado do servidor que não é executado dentro de qualquer tipo de estrutura.

A solução funciona muito bem, exceto que cada vez que um novo pedido é feito, abro uma nova conexão via MySQLdb.connect.

O que é o melhor "drop in" solução para mudar esta mais para usar o pool de conexão em python? Eu estou imaginando algo como a solução Commons DBCP para Java.

O processo está a correr muito tempo e tem muitos tópicos que precisa para fazer pedidos, mas não todos ao mesmo tempo ... especificamente eles fazem um monte de trabalho antes de rajadas curtas de escrever um pedaço de seus resultados.

Editado para adicionar: Depois de algum mais procura achei anitpool.py que parece decente, mas como eu sou relativamente novo para python Eu acho Eu só quero ter certeza que eu não estou sentindo falta de uma melhor solução mais óbvia / mais idiomática /.

Foi útil?

Solução

IMO, a "mais óbvia mais idiomática melhor solução / /" é usar um ORM existente em vez de inventar DAO-like classes.

Parece-me que ORM são mais populares do que as conexões SQL "brutos". Por quê? Porque Python é OO, eo mapeamento da linha SQL para a objeto é absolutamente essencial. Não há muitos casos em que você lidar com linhas SQL que não mapear para Python objetos.

Eu acho que SQLAlchemy ou SQLObject (e o pool de conexão associada), a solução mais Pythonic idiomática.

Pooling como um recurso separado não é muito comum, porque SQL puro (sem mapeamento objeto) não é muito popular para o tipo de processos complexos, de longa execução que beneficiam de pool de conexão. Sim, SQL puro é usado, mas é sempre usado em aplicações mais simples ou mais controlados, nos quais o pool não é útil.

Eu acho que você pode ter duas alternativas:

  1. Rever suas classes para usar SQLAlchemy ou SQLObject. Enquanto isso parece doloroso no início [todo esse trabalho desperdiçado], você deve ser capaz de aproveitar todo o design e pensamento e é meramente um exercício em adotar um ORM amplamente utilizado e solução de pooling.
  2. Role seu próprio pool de conexão simples usando o algoritmo que delineou - um simples Set ou lista de conexões que você percorrer.

Outras dicas

No MySQL?

Eu diria que não se preocupam com o pool de conexão. Eles são muitas vezes uma fonte de problemas e com o MySQL eles não vão trazer-lhe a vantagem de desempenho que você está esperando. Esta estrada pode ser um grande esforço para acompanhar - politicamente -. Porque há muito melhor mão práticas acenando e palavreado livro neste espaço sobre as vantagens do agrupamento de ligações

piscinas de conexão são simplesmente uma ponte entre o período pós-teia de aplicações sem estado (por exemplo, o protocolo HTTP) e a era pré-teia de aplicações de processamento em lote de vida longa com estado. Desde que as conexões eram muito caros em bancos de dados pré-web (já que ninguém usado para importam muito sobre quanto tempo uma conexão levou para estabelecer), as aplicações pós-web concebeu este esquema de pool de conexão de modo que cada hit não incorrer essa sobrecarga de processamento enorme no RDBMS.

Desde o MySQL é mais de um RDBMS web-era, as conexões são extremamente leve e rápido. Tenho escrito muitas aplicações web de alto volume que não usam um pool de conexão em tudo para MySQL.

Esta é uma complicação que você pode beneficiar de fazer sem, contanto que não há um obstáculo político para superar.

Enrole sua classe de conexão.

Defina um limite de quantas conexões você faz. Retornar uma ligação não utilizada. Intercept perto de libertar a ligação.

Update: I colocar algo como isso em dbpool.py:

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

discussão antiga, mas para o pool de uso geral (conexões ou qualquer objeto caro), eu uso algo como:

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

Que constrói preguiçosamente, tem um limite opcional e deve generalizar a qualquer caso de uso que eu posso pensar. Claro, isso pressupõe que você realmente precisa a partilha de qualquer recurso, que você não pode para muitos SQL-gostos modernos. Uso:

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

Este assume que tudo o que ctor objeto cria tem um destrutor apropriada, se necessário (alguns servidores não matam objetos de conexão, a menos que eles estão fechados explicitamente).

Acabei de ser olhando para o mesmo tipo de coisa.

Eu encontrei pysqlpool e piscina sqlalchemy módulo

Fazendo o seu próprio pool de conexão é uma idéia ruim se seu aplicativo sempre decide começar a usar o multi-threading. Fazendo um pool de conexão para uma aplicação multi-threaded é muito mais complicado do que um para uma aplicação single-threaded. Você pode usar algo como PySQLPool nesse caso.

Também é uma idéia ruim para usar um ORM, se você está olhando para o desempenho.

Se você estará lidando com enormes bancos de dados / pesados ??que têm que lidar com muita seleciona, inserções, atualizações e exclusões, ao mesmo tempo, então você está indo para o desempenho necessidade, o que significa que você precisará SQL personalizado escrito para pesquisas de otimizar e tempos de bloqueio. Com um ORM você geralmente não têm essa flexibilidade.

Então, basicamente, sim, você pode fazer a sua própria piscina de conexão e uso ORMs mas somente se você tem certeza que não vai precisar de nada do que acabei de descrever.

Respondendo a uma discussão antiga, mas a última vez que verifiquei, MySQL conexão ofertas pooling como parte de seus drivers.

Você pode vê-los em:

https: //dev.mysql .com / doc / conector-pitão / en / conector-pitão-ligação-pooling.html

De TFA, Supondo que você deseja abrir um pool de conexão explícita (como OP tinha afirmado):

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

Esta piscina é então acessado por solicitando a partir do conjunto através da função get_connection ().

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

Use DBUtils, simples e confiável.

pip install DBUtils
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top