it-swarm-eu.dev

Jaké je nejlepší řešení pro sdružování databázových připojení v pythonu?

Vyvinula jsem některé vlastní třídy podobné DAO, abych splnila některé velmi specializované požadavky na můj projekt, což je proces na straně serveru, který neběží uvnitř žádného rámce.

Řešení funguje skvěle kromě toho, že pokaždé, když je nový požadavek učiněn, otevírám nové připojení přes MySQLdb.connect.

Co je nejlepší řešení "drop in" přepnout na použití připojení sdružování v python? Představuji si něco jako společné řešení DBCP pro Javu.

Tento proces je dlouhodobý a má mnoho vláken, které potřebují, aby požadavky, ale ne všechny ve stejnou dobu ... konkrétně dělají dost práce před krátkými záblesky psaní kus jejich výsledků.

Upraveno pro přidání: Po nějakém dalším hledání jsem našel anitpool.py který vypadá slušně, ale protože jsem relativně nový v pythonu, myslím, že chci jen ujistit, že mi chybí více zřejmý/více idiomatický/lepší řešení.

31
John

IMO, “více zřejmý/více idiomatic/lepší řešení” je používat existující ORM spíše než vynalézat DAO-jako třídy.

Zdá se mi, že ORM jsou populárnější než "surové" SQL spojení. Proč? Protože Python je OO a mapování z řádku SQL do objektu je absolutně nezbytné. Není mnoho případů, kdy se jedná o řádky SQL, které nejsou mapovány na objekty Pythonu.

Myslím, že SQLAlchemy nebo SQLObject (a ​​související sdružování spojení) více idiomatické řešení Pythonic.

Sdružování jako samostatná funkce není příliš časté, protože čistý SQL (bez mapování objektů) není příliš populární pro takové složité, dlouhodobé procesy, které těží z sdružování připojení. Ano, čistý SQL is used, ale vždy se používá v jednodušších nebo více řízených aplikacích, kde sdružování není užitečné.

Myslím, že byste mohli mít dvě alternativy:

  1. Upravte své třídy tak, aby používaly SQLAlchemy nebo SQLObject. I když se to zpočátku jeví jako bolestivé (vše, co zbytečně zbytečné), měli byste být schopni využít veškerý design a myšlenky a je to jen cvičení při přijímání široce používaného řešení ORM a sdružování.
  2. Pomocí vlastního algoritmu, který jste načrtli, vytvořte svůj jednoduchý jednoduchý fond připojení - jednoduchá sada nebo seznam připojení, kterými procházíte. 
16
S.Lott

V MySQL?

Řekl bych, že se neobtěžujte s sdružováním připojení. Často jsou zdrojem problémů a MySQL vám nepřinesou výkonnostní výhodu, o kterou doufáte. Tato cesta může být velkým úsilím následovat - politicky - protože v tomto prostoru je tolik nejlepších praktik mávání rukou a textových slovesností o výhodách sdružování spojení.

Spojovací fondy jsou jednoduše mostem mezi post-web éry aplikací bez státní příslušnosti (např. Protokol HTTP) a éry předběžného webového zpracování stavových aplikací pro dlouhodobé dávkové zpracování. Vzhledem k tomu, že připojení byla v přednastavených databázích velmi drahá (protože nikdo se příliš nezajímal o to, jak dlouho bylo spojení navázáno), post-web aplikace vymyslely tento systém propojení bazénů, takže každý hit nevytvořil tento obrovský režijní proces. o RDBMS.

Vzhledem k tomu, že MySQL je více web-era RDBMS, spojení jsou extrémně lehká a rychlá. Napsal jsem mnoho velkých objemových webových aplikací, které pro MySQL vůbec nepoužívají fond připojení.

Je to komplikace, kterou můžete mít z toho, že děláte bez, pokud není překonána politická překážka.

22
mbac32768

Zabalte třídu připojení.

Nastavte limit počtu provedených připojení. Vraťte nepoužité připojení. Zastavte připojení a uvolněte připojení.

Aktualizace: Vložil jsem něco takového do souboru dbpool.py:

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

Staré vlákno, ale pro univerzální sdružování (spojení nebo nějaký drahý objekt), používám něco jako:

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

Které konstrukty líně, má volitelný limit, a měly by zobecnit všechny případy použití, na které si myslím. Samozřejmě, to předpokládá, že opravdu potřebujete sdružování jakéhokoliv zdroje, který nemusíte pro mnoho moderních SQL-likes. Používání:

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

To předpokládá, že jakýkoliv objekt ctor vytvoří v případě potřeby vhodný destruktor (některé servery nezabíjejí objekty připojení, pokud nejsou explicitně uzavřeny).

6
metaperture

Právě jsem hledal něco podobného.

Našel jsem pysqlpool a modul bazénů sqlalchemy

2
Willie

Vytvoření vlastního fondu připojení je BAD myšlenka, pokud se vaše aplikace rozhodne začít používat multi-threading. Vytvoření fondu připojení pro aplikace s více podprocesy je mnohem složitější než pro aplikaci s jedním podprocesem. V takovém případě můžete použít něco jako PySQLPool.

Je to také BAD nápad použít ORM, pokud hledáte výkon.

Pokud se budete zabývat rozsáhlými/těžkými databázemi, které musí zvládnout spoustu výběrů, vložek, aktualizací a mazání najednou, budete potřebovat výkon. SQL napsal optimalizovat vyhledávání a uzamčení časy. S ORM obvykle nemáte takovou flexibilitu.

Takže, v podstatě, můžete si vytvořit vlastní fond připojení a používat ORM, ale pouze pokud si nejste jisti, že nebudete potřebovat nic z toho, co jsem právě popsal.

2
flexo

Odpověď na staré vlákno, ale když jsem naposledy zkontroloval, MySQL nabízí sdružování připojení jako součást svých ovladačů.

Můžete je zkontrolovat na adrese:

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

Z TFA: Za předpokladu, že chcete otevřít fond připojení explicitně (jak uvedl OP):

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

Tento fond je pak zpřístupněn požadavkem z fondu prostřednictvím funkce get_connection ().

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

Použijte DBUtils, jednoduché a spolehlivé.

pip install DBUtils

0
ospider