Quelle est la meilleure solution pour le regroupement de connexions de bases de données en python?

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

Question

J'ai développé des classes de type DAO personnalisées pour répondre à certaines exigences très spécifiques de mon projet. Il s'agit d'un processus côté serveur qui ne s'exécute dans aucun type de cadre.

La solution fonctionne très bien, sauf que chaque fois qu'une nouvelle demande est faite, j'ouvre une nouvelle connexion via MySQLdb.connect.

Quel est le meilleur "drop in"? solution pour passer à l'utilisation du regroupement de connexions en python? J'imagine quelque chose comme la solution commune DBCP pour Java.

Le processus est long et a beaucoup de threads qui doivent faire des demandes, mais pas tous en même temps ... spécifiquement ils font beaucoup de travail avant l'éclatement d'une courte période d'écriture d'une partie de leurs résultats.

Édité pour ajouter: Après quelques recherches supplémentaires, je trouvais anitpool.py une apparence décente, mais comme je suis relativement nouveau en python, je suppose Je veux juste m'assurer que je ne manque pas d'une solution plus évidente / plus idiomatique / meilleure.

Était-ce utile?

La solution

IMO, la "solution plus évidente / plus idiomatique / meilleure" est d'utiliser un ORM existant plutôt que d'inventer des classes de type DAO.

Il me semble que les ORM sont plus populaires que "brut". Connexions SQL. Pourquoi? Parce que Python est OO et que le mappage de la ligne SQL vers l'objet est absolument essentiel. Il n'y a pas beaucoup de cas où vous traitez avec des lignes SQL qui ne mappent pas aux objets Python.

Je pense que SQLAlchemy ou SQLObject (et le regroupement de connexions associé) la solution plus idiomatique de Pythonic.

Le regroupement en tant que fonctionnalité distincte n’est pas très courant, car le SQL pur (sans mappage d’objet) n’est pas très utilisé pour le type de processus complexes à exécution longue qui bénéficient du regroupement de connexions. Oui, le SQL pur est utilisé, mais il est toujours utilisé dans des applications plus simples ou plus contrôlées où la mise en pool n'est pas utile.

Je pense que vous pourriez avoir deux alternatives:

  1. Modifiez vos classes pour qu'elles utilisent SQLAlchemy ou SQLObject. Bien que cela semble douloureux au début [tout ce travail gaspillé], vous devriez être en mesure de tirer parti de toute la conception et de la pensée. Il ne s’agit que d’un exercice consistant à adopter une solution ORM et de mise en commun largement utilisée.
  2. Lancez votre propre pool de connexions simples en utilisant l'algorithme que vous avez décrit - un simple ensemble ou une liste de connexions que vous parcourez.

Autres conseils

Dans MySQL?

Je dirais ne vous embêtez pas avec le regroupement des connexions. Ils sont souvent une source de problèmes et avec MySQL, ils ne vous apporteront pas l’avantage de performances que vous espériez. Cette voie pourrait faire l’objet de beaucoup d’efforts - sur le plan politique - car il existe dans cet espace une foule de pratiques exemplaires et de verbiage sur les avantages du regroupement des connexions.

Les pools de connexions constituent simplement un pont entre l'ère post-Web des applications sans état (protocole HTTP, par exemple) et l'ère pré-Web des applications de traitement par lots longue durée avec état. Étant donné que les connexions dans les bases de données pré-Web étaient très coûteuses (personne ne se souciant trop du temps qu’il fallait pour établir une connexion), les applications post-Web ont conçu ce schéma de pool de connexions de manière à ce que chaque hit n’entraîne pas cette surcharge de traitement. sur le SGBDR.

Etant donné que MySQL est davantage un SGBDR basé sur le Web, les connexions sont extrêmement légères et rapides. J'ai écrit de nombreuses applications Web à volume élevé qui n'utilisent pas du tout un pool de connexions pour MySQL.

C’est une complication dont vous pouvez tirer parti, s’il n’ya pas d’obstacle politique à surmonter.

Emballez votre classe de connexion.

Limitez le nombre de connexions que vous établissez. Renvoyer une connexion inutilisée. Intercepter près pour libérer la connexion.

Mise à jour: Je mets quelque chose comme ça dans dbpool.py:

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

Ancien fil de discussion, mais pour le pooling à usage général (connexions ou objets coûteux), j'utilise quelque chose comme:

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

Ce qui construit paresseusement, a une limite optionnelle et devrait être généralisé à tous les cas d’utilisation auxquels je peux penser. Bien entendu, cela suppose que vous ayez vraiment besoin de la mise en pool de toutes les ressources, ce qui n'est pas le cas pour de nombreux SQL-like modernes. Utilisation:

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

Cela suppose que l'objet créé par ctor possède un destructeur approprié si nécessaire (certains serveurs ne suppriment pas les objets de connexion à moins qu'ils ne soient fermés explicitement).

Je viens de chercher le même genre de chose.

J'ai trouvé pysqlpool et le module de pool sqlalchemy

Créer votre propre pool de connexion est une mauvaise idée si votre application décide de commencer à utiliser le multi-threading. La création d'un pool de connexions pour une application multithread est beaucoup plus compliquée que celle d'une application mono-thread. Vous pouvez utiliser quelque chose comme PySQLPool dans ce cas.

C’est aussi une mauvaise idée d’utiliser un ORM si vous recherchez des performances.

Si vous traitez avec des bases de données énormes / lourdes qui doivent gérer beaucoup de sélections, inserts, met à jour et supprime en même temps, vous aurez besoin de performances, ce qui signifie que vous aurez besoin de SQL écrit personnalisé pour optimiser les recherches et les temps de verrouillage. Avec un ORM, vous n’avez généralement pas cette souplesse.

En gros, vous pouvez créer votre propre pool de connexion et utiliser des ORM, mais uniquement si vous êtes certain de ne pas avoir besoin de ce que je viens de décrire.

En réponse à un ancien thread, mais la dernière fois que j'ai vérifié, MySQL propose le regroupement de connexions dans le cadre de ses pilotes.

Vous pouvez les consulter à l'adresse suivante:

  

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

À partir de TFA, en supposant que vous souhaitiez ouvrir un pool de connexions de manière explicite (comme l'OP l'avait indiqué):

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

On accède ensuite à ce pool en effectuant une demande auprès du pool via la fonction get_connection ().

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

Utilisez DBUtils , simple et fiable.

pip install DBUtils
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top