Domanda

Ho sviluppato alcune classi personalizzate simili a DAO per soddisfare alcuni requisiti molto specializzati per il mio progetto che è un processo lato server che non viene eseguito all'interno di alcun tipo di framework.

La soluzione funziona benissimo, tranne per il fatto che ogni volta che viene effettuata una nuova richiesta, apro una nuova connessione tramite MySQLdb.connect.

Qual è la migliore soluzione "drop in" per passare all'utilizzo del pool di connessioni in Python?Sto immaginando qualcosa di simile alla soluzione DBCP comune per Java.

Il processo è lungo e ha molti thread che necessitano di effettuare richieste, ma non tutti contemporaneamente...in particolare, svolgono un bel po' di lavoro prima di scrivere brevemente una parte dei loro risultati.

Modificato per aggiungere:Dopo qualche altra ricerca ho trovato anitpool.py che sembra decente, ma dato che sono relativamente nuovo in Python, immagino di voler solo assicurarmi di non perdere una soluzione più ovvia/più idiomatica/migliore.

È stato utile?

Soluzione

IMO, la "soluzione più ovvia/più idiomatica/migliore" è utilizzare un ORM esistente anziché inventare classi simili a DAO.

Mi sembra che gli ORM siano più popolari delle connessioni SQL "grezze".Perché?Perché Pitone È OO e la mappatura dalla riga SQL all'oggetto È assolutamente essenziale.Non ci sono molti casi in cui hai a che fare con righe SQL che non sono mappate su oggetti Python.

penso che SQLAlchemy O SQLObject (e il pool di connessioni associato) la soluzione Pythonica più idiomatica.

Il pooling come funzionalità separata non è molto comune perché l'SQL puro (senza mappatura degli oggetti) non è molto popolare per il tipo di processi complessi e di lunga esecuzione che traggono vantaggio dal pooling delle connessioni.Sì, SQL puro È utilizzato, ma viene sempre utilizzato in applicazioni più semplici o più controllate in cui il pooling non è utile.

Penso che potresti avere due alternative:

  1. Rivedi le tue classi per utilizzare SQLAlchemy o SQLObject.Sebbene all'inizio ciò sembri doloroso [tutto quel lavoro sprecato], dovresti essere in grado di sfruttare tutta la progettazione e il pensiero ed è semplicemente un esercizio per adottare una soluzione ORM e di pooling ampiamente utilizzata.
  2. Crea il tuo semplice pool di connessioni utilizzando l'algoritmo che hai delineato: un semplice set o elenco di connessioni da scorrere.

Altri suggerimenti

InMySQL?

Direi di non preoccuparsi del pooling delle connessioni.Sono spesso fonte di problemi e con MySQL non ti offriranno il vantaggio in termini di prestazioni che speri.Questa strada potrebbe richiedere molto impegno da seguire, politicamente, perché ci sono così tante buone pratiche che agitano le mani e verbosità da manuale in questo spazio sui vantaggi del pooling delle connessioni.

I pool di connessioni sono semplicemente un ponte tra l'era post-web delle applicazioni stateless (ad es.protocollo HTTP) e l'era pre-web delle applicazioni di elaborazione batch con stato e di lunga durata.Poiché le connessioni erano molto costose nei database pre-web (poiché nessuno si preoccupava troppo del tempo necessario per stabilire una connessione), le applicazioni post-web hanno ideato questo schema di pool di connessioni in modo che ogni colpo non comportasse questo enorme sovraccarico di elaborazione sull'RDBMS.

Poiché MySQL è più un RDBMS dell'era web, le connessioni sono estremamente leggere e veloci.Ho scritto molte applicazioni Web ad alto volume che non utilizzano affatto un pool di connessioni per MySQL.

Questa è una complicazione di cui potresti trarre vantaggio dal fare a meno, purché non ci sia un ostacolo politico da superare.

Avvolgi la tua classe di connessione.

Imposta un limite al numero di connessioni effettuate.Restituisce una connessione inutilizzata.Intercetta vicino per liberare la connessione.

Aggiornamento:Ho inserito qualcosa del genere in dbpool.py:

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

Vecchio thread, ma per il pooling generico (connessioni o qualsiasi oggetto costoso), utilizzo qualcosa del tipo:

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

Che si costruisce pigramente, ha un limite facoltativo e dovrebbe generalizzarsi a qualsiasi caso d'uso a cui riesco a pensare.Naturalmente, ciò presuppone che tu abbia davvero bisogno del pool di qualsiasi risorsa, cosa che potresti non fare per molti moderni SQL simili.Utilizzo:

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

Ciò presuppone che qualunque oggetto creato da ctor abbia un distruttore appropriato, se necessario (alcuni server non interrompono gli oggetti di connessione a meno che non vengano chiusi esplicitamente).

Sto proprio cercando lo stesso genere di cose.

ho trovato pysqlpool e il modulo pool sqlalchemy

Creare il tuo pool di connessioni è una pessima idea se la tua app decide di iniziare a utilizzare il multi-threading.Creare un pool di connessioni per un'applicazione multi-thread è molto più complicato di uno per un'applicazione a thread singolo.In questo caso puoi usare qualcosa come PySQLPool.

È anche una pessima idea utilizzare un ORM se stai cercando prestazioni.

Se hai a che fare con database enormi/pesanti che devono gestire molti selezioni, inserti, aggiornamenti ed eliminate contemporaneamente, allora avrai bisogno di prestazioni, il che significa che avrai bisogno di SQL personalizzato per ottimizzare le ricerche e tempi di blocco.Con un ORM di solito non hai quella flessibilità.

Quindi, in sostanza, sì, puoi creare il tuo pool di connessioni e utilizzare gli ORM, ma solo se sei sicuro di non aver bisogno di nulla di ciò che ho appena descritto.

Rispondendo a un vecchio thread ma l'ultima volta che ho controllato, MySQL offre il pooling delle connessioni come parte dei suoi driver.

Puoi verificarli su:

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

Da TFA, supponendo che tu voglia aprire esplicitamente un pool di connessioni (come aveva affermato OP):

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

A questo pool si accede quindi richiedendo dal pool tramite la funzione get_connection().

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

Utilizzo DBUtils, semplice e affidabile.

pip install DBUtils
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top