¿Cuál es la mejor solución para la agrupación de conexiones de bases de datos en Python?

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

Pregunta

He desarrollado algunas clases personalizadas tipo DAO para cumplir con algunos requisitos muy especializados para mi proyecto, que es un proceso del lado del servidor que no se ejecuta dentro de ningún tipo de marco.

La solución funciona muy bien excepto que cada vez que se realiza una nueva solicitud, abro una nueva conexión a través de MySQLdb.connect.

¿Cuál es la mejor solución inmediata para cambiar esto y utilizar la agrupación de conexiones en Python?Me estoy imaginando algo así como la solución DBCP común para Java.

El proceso es largo y tiene muchos hilos que necesitan realizar solicitudes, pero no todos al mismo tiempo...específicamente, trabajan bastante antes de breves períodos de escribir una parte de sus resultados.

Editado para agregar:Después de buscar un poco más encontré anitpool.py lo cual parece decente, pero como soy relativamente nuevo en Python, supongo que solo quiero asegurarme de no perderme una solución más obvia/más idiomática/mejor.

¿Fue útil?

Solución

En mi opinión, la "solución más obvia/más idiomática/mejor" es utilizar un ORM existente en lugar de inventar clases similares a DAO.

Me parece que los ORM son más populares que las conexiones SQL "sin procesar".¿Por qué?Porque pitón es OO y el mapeo de una fila SQL a un objeto es absolutamente esencial.No hay muchos casos en los que se trate con filas de SQL que no se asignan a objetos de Python.

Creo que SQLAlquimia o Objeto SQL (y la agrupación de conexiones asociada) la solución Pythonic más idiomática.

La agrupación como característica separada no es muy común porque SQL puro (sin mapeo de objetos) no es muy popular para el tipo de procesos complejos y de larga duración que se benefician de la agrupación de conexiones.Sí, SQL puro es Se usa, pero siempre se usa en aplicaciones más simples o más controladas donde la agrupación no es útil.

Creo que podrías tener dos alternativas:

  1. Revise sus clases para usar SQLAlchemy o SQLObject.Si bien esto parece doloroso al principio [todo ese trabajo desperdiciado], debería poder aprovechar todo el diseño y la idea y es simplemente un ejercicio para adoptar un ORM y una solución de agrupación ampliamente utilizados.
  2. Cree su propio grupo de conexiones simple utilizando el algoritmo que describió: un conjunto o lista simple de conexiones por las que recorre.

Otros consejos

¿En MySQL?

Yo diría que no se moleste con la agrupación de conexiones.A menudo son una fuente de problemas y con MySQL no le brindarán la ventaja de rendimiento que espera.Este camino puede requerir un gran esfuerzo (políticamente) porque hay muchas mejores prácticas y palabrería de libros de texto en este espacio sobre las ventajas de la agrupación de conexiones.

Los grupos de conexiones son simplemente un puente entre la era post-web de las aplicaciones sin estado (p. ej.protocolo HTTP) y la era anterior a la web de aplicaciones de procesamiento por lotes con estado y de larga duración.Dado que las conexiones eran muy costosas en las bases de datos anteriores a la web (ya que nadie solía preocuparse demasiado por cuánto tiempo tardaba en establecerse una conexión), las aplicaciones posteriores a la web idearon este esquema de grupo de conexiones para que cada visita no incurriera en esta enorme sobrecarga de procesamiento. en el RDBMS.

Dado que MySQL es más bien un RDBMS de la era web, las conexiones son extremadamente ligeras y rápidas.He escrito muchas aplicaciones web de gran volumen que no utilizan ningún grupo de conexiones para MySQL.

Esta es una complicación de la que puede resultar beneficioso prescindir, siempre y cuando no haya un obstáculo político que superar.

Envuelve tu clase de conexión.

Establece un límite en la cantidad de conexiones que realizas.Devuelve una conexión no utilizada.Interceptar cerca para liberar la conexión.

Actualizar:Puse algo como esto en dbpool.py:

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

Hilo antiguo, pero para agrupaciones de propósito general (conexiones o cualquier objeto costoso), 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 se construye de manera perezosa, tiene un límite opcional y debería generalizarse a cualquier caso de uso que se me ocurra.Por supuesto, esto supone que realmente necesita agrupar cualquier recurso, lo que puede que no sea necesario para muchos SQL modernos.Uso:

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

Esto supone que cualquier objeto que cree ctor tiene un destructor apropiado si es necesario (algunos servidores no eliminan los objetos de conexión a menos que estén cerrados explícitamente).

He estado buscando el mismo tipo de cosas.

He encontrado piscinapysql y el módulo de grupo sqlalchemy

Crear su propio grupo de conexiones es una MALA idea si su aplicación alguna vez decide comenzar a usar subprocesos múltiples.Crear un grupo de conexiones para una aplicación de subprocesos múltiples es mucho más complicado que uno para una aplicación de un solo subproceso.Puedes usar algo como PySQLPool en ese caso.

También es una MALA idea utilizar un ORM si buscas rendimiento.

Si se ocupará de bases de datos enormes/pesadas que tienen que manejar muchas selecciones, inserciones, actualizaciones y eliminaciones al mismo tiempo, entonces necesitará rendimiento, lo que significa que necesitará SQL personalizado escrito para optimizar las búsquedas y bloquear los tiempos.Con un ORM normalmente no tienes esa flexibilidad.

Básicamente, sí, puedes crear tu propio grupo de conexiones y usar ORM, pero solo si estás seguro de que no necesitarás nada de lo que acabo de describir.

Respondiendo a un hilo antiguo, pero la última vez que lo revisé, MySQL ofrece agrupación de conexiones como parte de sus controladores.

Puedes consultarlos en:

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

Desde TFA, suponiendo que desea abrir un grupo de conexiones explícitamente (como había indicado OP):

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

Luego se accede a este grupo solicitándolo desde el grupo a través de la función get_connection().

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

Usar DBUtils, simple y confiable.

pip install DBUtils
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top