it-swarm-tr.com

Python'da veritabanı bağlantısı havuzu için en iyi çözüm nedir?

Herhangi bir çerçevede çalışmayan, sunucu tarafı bir süreç olan projem için çok özel gereksinimleri karşılamak için bazı özel DAO benzeri sınıflar geliştirdim.

Çözüm, her yeni bir istek yapıldığında, MySQLdb.connect ile yeni bir bağlantı açmam dışında harika çalışıyor.

Bunu python'da bağlantı havuzu kullanmaya geçirmenin en iyi "bırakma" çözümü nedir? Java için commons DBCP çözümü gibi bir şey hayal ediyorum.

Süreç uzun sürüyor ve talepte bulunulması gereken birçok iş parçacığı var, ancak hepsi aynı anda değil ... özellikle sonuçlarının bir kısmını yazmadan önce çok fazla iş yapıyorlar.

Eklemek için düzenlendi: Biraz daha arama yaptıktan sonra anitpool.py 'ı iyi buldum, ancak python için nispeten yeni olduğum için sanırım daha belirgin/daha deyimsel bir özlem eksik olduğundan emin olmak istiyorum daha iyi çözüm.

31
John

IMO, "daha açık/daha deyimsel/daha iyi bir çözüm", DAO benzeri sınıflar icat etmek yerine mevcut bir ORM kullanmaktır.

Bana öyle geliyor ki ORM'ler "ham" SQL bağlantılarından daha popüler. Niye ya? Çünkü Python is OO ve SQL satırından is nesnesine eşleme kesinlikle gereklidir. Python nesnelerine eşlenmeyen SQL satırlarıyla uğraştığınız birçok durum yoktur.

Bence SQLAlchemy veya SQLObject (ve ilgili bağlantı havuzu) daha deyimsel Pythonic çözümü.

Ayrı bir özellik olarak havuzlama çok yaygın değildir, çünkü saf SQL (nesne eşlemesi olmadan), bağlantı havuzundan yararlanan karmaşık, uzun süreli işlemler için çok popüler değildir. Evet, saf SQL is kullanılmış, ancak havuzlamanın yararlı olmadığı daha basit veya daha kontrollü uygulamalarda kullanılır.

İki alternatifiniz olabileceğini düşünüyorum:

  1. SQLAlchemy veya SQLObject kullanmak için sınıflarınızı değiştirin. Bu, ilk başta [boşa harcanan her şey] acı verici görünmekle birlikte, tüm tasarım ve düşünceden yararlanabilmelisiniz ve bu yalnızca yaygın olarak kullanılan bir ORM ve havuzlama çözümünün benimsenmesi için bir egzersizdir.
  2. Özetlediğiniz algoritmayı kullanarak kendi basit bağlantı havuzunuzu yuvarlayın - basitçe Döndürdüğünüz bağlantıların bir Set veya Listesini kullanın. 
16
S.Lott

MySQL'de mi?

Bağlantı havuzu ile uğraşma derim. Genellikle sıkıntı kaynağı olurlar ve MySQL ile umduğunuz performans avantajını size getiremezler. Bu yol takip etmek için çok çaba sarf edebilir - politik olarak - çünkü el sallama ve kitap okuma becerilerini bu alanda bağlantı havuzlamanın avantajları hakkında çok iyi uygulamalar vardır.

Bağlantı havuzları, durumsuz uygulamaların web sonrası dönemi (örneğin, HTTP protokolü) ile durumlu uzun ömürlü toplu işlem uygulamalarının web öncesi dönemi arasında bir köprüdür. Web öncesi veritabanlarında bağlantılar çok pahalı olduğu için (hiç kimse bir bağlantının kurulmasının ne kadar sürdüğünü çok fazla önemsemediği için), web sonrası uygulamalar bu bağlantı havuzu düzenini tasarladı, böylece her isabet bu devasa işlem yüküne uğramayacaktı. RDBMS’de.

MySQL, bir web dönemi RDBMS'sinden daha fazla olduğu için, bağlantılar son derece hafif ve hızlıdır. MySQL için hiç bağlantı havuzu kullanmayan birçok yüksek hacimli web uygulaması yazdım.

Bu, üstesinden gelmek için siyasi bir engel olmadığı sürece, onsuz yapmaktan yararlanabileceğiniz bir komplikasyondur.

22
mbac32768

Bağlantı sınıfınızı kaydırın.

Kaç bağlantı yaptığınızla ilgili bir sınır belirleyin. Kullanılmayan bir bağlantı verin.

Güncelleme: Dbpool.py içine böyle bir şey koymak:

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

Eski iş parçacığı, ancak genel amaçlı havuz (bağlantılar veya herhangi bir pahalı nesne) için, şöyle bir şey kullanıyorum:

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

Tembel inşa eden, isteğe bağlı bir sınırı vardır ve düşünebildiğim herhangi bir kullanım durumuna genellemelidir. Elbette bu, birçok modern SQL beğenisine sahip olamayabileceğiniz kaynakların bir araya gelmesine gerçekten ihtiyacınız olduğunu varsayar. Kullanımı:

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

Bu, ctorun yarattığı her ne olursa olsun ihtiyaç duyulan uygun bir yıkıcıya sahip olduğunu varsayar (bazı sunucular açıkça kapatılmadıkça bağlantı nesnelerini öldürmez).

6
metaperture

Sadece aynı şeyi arıyorum.

Buldum pysqlpool ve sqlalchemy havuz modülü

2
Willie

Uygulamanız çoklu iş parçacığı kullanmaya başlamaya karar verirse, kendi bağlantı havuzunuzu oluşturmak BAD fikridir. Çok iş parçacıklı bir uygulama için bir bağlantı havuzu oluşturmak, tek iş parçacıklı bir uygulama için olandan çok daha karmaşıktır. Bu durumda PySQLPool gibi bir şey kullanabilirsiniz.

Performans arıyorsanız, ORM kullanmak da bir BAD fikridir.

Aynı anda birçok seçim, ek, Güncelleme ve silme işlemine ihtiyaç duyan devasa/ağır veritabanlarıyla ilgileniyorsanız, performansa ihtiyacınız olacak, bu da özel bir ihtiyaç duyacağınız anlamına gelir SQL aramaları ve kilitlenme sürelerini optimize etmek için yazılmıştır. Bir ORM ile genellikle bu esnekliğe sahip olmazsınız.

Yani, temel olarak, evet, kendi bağlantı havuzunuzu oluşturabilir ve ORM'leri kullanabilirsiniz, ancak sadece tanımladığım şeyden hiçbir şeye ihtiyacınız olmayacağından eminseniz.

2
flexo

Eski bir konuya cevap verip son kontrol ettiğimde, MySQL sürücülerinin bir parçası olarak bağlantı havuzu oluşturuyor.

Bunları kontrol edebilirsiniz:

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

TFA’dan açıkça bir bağlantı havuzu açmak istediğinizi varsayarsak (OP’nin dediği gibi):

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

Bu havuza daha sonra havuzdan get_connection () fonksiyonu ile istekte bulunarak erişilebilir.

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

DBUtils, basit ve güvenilir kullanın.

pip install DBUtils

0
ospider