Frage

Ich habe einige benutzerdefinierten DAO-Klassen wie entwickeln einige sehr spezielle Anforderungen für mein Projekt zu erfüllen, die ein serverseitige Prozess ist, der innerhalb jeder Art von Rahmen nicht ausgeführt.

Die Lösung funktioniert gut, außer, dass jedes Mal, wenn eine neue Anforderung gemacht wird, ich öffne eine neue Verbindung über MySQLdb.connect.

Was ist die beste „drop-in“ -Lösung diese wechseln Connection Pooling in Python zu verwenden? Ich stelle mir vor so etwas wie die commons DBCP Lösung für Java.

Der Prozess ist mit langer Laufzeit und viele Threads hat, die Anfragen machen müssen, aber nicht alle zur gleichen Zeit ... speziell sie ziemlich viel Arbeit vor kurzen Bursts des Schreibens ein Stück ihrer Ergebnisse aus.

Edited hinzufügen: Nach weiterer Suche fand ich anitpool.py die anständig aussieht, aber wie ich relativ neu bin in Python Ich denke, ich möchte nur sicherstellen, dass ich nicht mehr auf der Hand / mehr idiomatische / bessere Lösung fehlt.

War es hilfreich?

Lösung

IMO, die „offensichtliche / mehr idiomatische / bessere Lösung“ ist eine vorhandene ORM zu verwenden, anstatt DAO-Klassen wie zu erfinden.

Es scheint mir, dass ORM sind beliebter als „raw“ SQL-Verbindungen. Warum? Da Python ist OO, und die Zuordnung von SQL-Zeile zum Objekt ist unbedingt erforderlich. Es gibt nicht viele Fälle, in denen Sie mit SQL Zeilen beschäftigen, die Python-Objekte abbilden nicht.

Ich denke, dass SQLAlchemy oder SQLObject (und das damit verbundene Verbindungs-Pooling), desto mehr idiomatische Pythonic Lösung.

Pooling als separates Feature ist nicht sehr verbreitet, weil reine SQL (ohne Objekt-Mapping) für die Art von komplexen, lang laufenden Prozessen nicht sehr beliebt ist, die von Connection Pooling profitieren. Ja, reiner SQL ist verwendet, aber es ist immer einfacher und kontrollierte Anwendungen eingesetzt, in denen Pooling nicht hilfreich ist.

Ich glaube, Sie könnten zwei Alternativen haben:

  1. Arbeiten Sie Ihre Klassen SQLAlchemy oder SQLObject zu verwenden. Während dies auf den ersten schmerzhaft erscheint [ganze Arbeit verschwendet], sollten Sie alle das Design und die Gedanken zu nutzen in der Lage, und es ist nur eine Übung in einer weit verbreiteten Annahme ORM und Pooling-Lösung.
  2. Bewegen Sie Ihre eigenen einfachen Verbindungspool mit dem Algorithmus Sie skizziert - eine einfache Set oder Liste der Verbindungen, die Sie durchlaufen.

Andere Tipps

In MySQL?

Ich würde sagen, nicht mit dem Connection-Pooling stören. Sie sind oft eine Quelle von Schwierigkeiten und mit MySQL sie gehen nicht, dass Sie den Leistungsvorteil zu bringen für Sie hoffen. Diese Straße kann sehr viel Mühe zu folgen - politisch -. Weil es so viel Best Practices Hand winkt und Lehrbuch Wortschwall in diesem Raum über die Vorteile des Verbindungs-Pooling

Verbindungspools sind einfach eine Brücke zwischen der Post-Web-Ära der staatenlos Anwendungen (zum Beispiel HTTP-Protokoll) und die Pre-Bahn Ära der Stateful langlebiger Stapelverarbeitung Anwendungen. Da Verbindungen in sehr teuer waren pre-Web-Datenbanken (da niemand zu viel kümmern verwendet, wie lange eine Verbindung herzustellen nahm), Post-Web-Anwendungen entwickelt, um dieses Schema Connection-Pools, so dass jeder Treffer nicht diesen riesigen Verarbeitungsaufwand entstehen hat auf dem RDBMS.

Da MySQL mehr eine Web-Ära RDBMS ist, Verbindungen sind extrem leicht und schnell. Ich habe viele hochvolumigen Web-Anwendungen geschrieben, die keine Verbindung Pool überhaupt für MySQL verwenden Sie.

Dies ist eine Komplikation Sie tun, ohne, so lange profitieren können, da es kein politisches Hindernis zu überwinden.

Wickeln Sie Ihre Verbindungsklasse.

Ein Limit, wie viele Verbindungen, die Sie machen. Rück eine nicht verwendete Verbindung. Abfängt schließt die Verbindung zu befreien.

Update: Ich habe so etwas wie dies in dbpool.py:

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

Alt Faden, sondern für allgemeine Zwecke Pooling (Verbindungen oder jedes teures Objekt), verwende ich so etwas wie:

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

Welche lazily konstruiert, verfügt über eine optionale Grenze und sollte auf jeden Anwendungsfall verallgemeinern ich mir vorstellen kann. Natürlich setzt dies voraus, dass Sie wirklich die Bündelung von was auch immer Ressource benötigen, die Sie möglicherweise nicht für viele moderne SQL-likes. Verbrauch:

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

Dies ist davon ausgehen, dass jedes Objekt Ctor schafft eine angemessene destructor hat, wenn nötig (einige Server nicht töten Verbindungsobjekte, wenn sie nicht explizit geschlossen werden).

Ich habe für die gleiche Art der Sache gerade suchen.

ich gefunden habe pysqlpool und der sqlalchemy Pool Modul

Ihre eigene Verbindung Pool macht, ist eine schlechte Idee, wenn Sie Ihre App immer Multi-Threading zu starten entscheiden verwenden. einen Verbindungspool für eine Multi-Threaded-Anwendung zu machen ist viel komplizierter, als man für eine Single-Threaded-Anwendung. Sie können in diesem Fall so etwas wie PySQLPool verwenden.

Es ist auch eine schlechte Idee, ein ORM zu verwenden, wenn Sie für die Leistung suchen.

Wenn Sie mit großen / schweren Datenbanken zu tun, die eine Menge wählt, Einsätze verarbeiten müssen, Updates und zur gleichen Zeit löscht, dann werden Sie die Leistung benötigen, was bedeutet, dass Sie geschrieben benutzerdefinierten SQL benötigen Lookups zu optimieren und sperren Zeiten. Mit einem ORM müssen Sie nicht in der Regel, dass die Flexibilität.

Also im Grunde, ja, können Sie Ihren eigenen Connection-Pool machen und ORMs verwenden, aber nur, wenn Sie sicher sind, werden Sie nichts von benötigen, was ich gerade beschrieben wird.

zu einem alten Thread antworten, aber das letzte Mal habe ich geprüft, MySQL bietet Connection-Pooling als Teil seiner Fahrer.

Sie können sie überprüfen unter:

  

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

Von TFA, Angenommen, Sie möchten explizit eine Verbindung Pool öffnen (wie OP angegeben hatte):

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

Dieser Pool wird dann durch Anforderung aus dem Pool durch die get_connection () Funktion aufgerufen.

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

Mit DBUtils, einfach und zuverlässig.

pip install DBUtils
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top