2015-04-14 22 views
14

Biz sqlalchemy bağlantı kesmek işleme ve bunun ORM ile nasıl entegre olduğunu deneyler. Biz dokümanlar inceledim ve tavsiye, bağlantı kesme istisnayı yakalamak bir rollback() sorunu ve kod yeniden denemek için gibi görünüyor.sqlalchemy işlemek için daha iyi bir yaklaşım keser

örn:

import sqlalchemy as SA 

retry = 2 
while retry: 
    retry -= 1 
    try: 
     for name in session.query(Names): 
      print name 
     break 
    except SA.exc.DBAPIError as exc: 
     if retry and exc.connection_invalidated: 
      session.rollback() 
     else: 
      raise 

Ben gerekçesini izleyin - Herhangi etkin işlemler geri alma ve eylemlerin tutarlı sıralamasını sağlamak için onları tekrar zorundayız.

AMA - bu, veriyle çalışmak isteyen her işleve fazladan bir kod ekleneceği anlamına gelir. Ayrıca, SELECT söz konusu olduğunda, verileri değiştirmiyoruz ve geri alma/yeniden istek kavramı sadece çirkin değil, aynı zamanda DRY ilkesini ihlal ediyor (kendinizi tekrar etmeyin).

Başkalarının şüphe uyandırıcılarla bağlantı kesimlerini nasıl ele aldıklarını paylaştığını düşünürler mi diye merak ediyordum.

Bilginize: SQLAlchemy 0.9.8 ve Postgres 9.2.9

+1

Şu anda [Kötümser Bağlantı Kesme İşlemi] (http://docs.sqlalchemy.org/en/latest/core/pooling.html#disconnect-handling-pessimistic) kullanarak * bazı * başarıyı azaltmak için MySQL var gitti. Yine de bu durumdan kurtulamayacağımız bir yerde üretimde bir dava görüyoruz ve işlem geri alınamaz ve takılıp kalmaz. Her ne kadar bu iki işleme (ZODB ve SQL) katılacağımız ve [İki Aşamalı işler] (http://docs.sqlalchemy.org/en/latest/orm/ session_transaction.html # enable-two-phase-commit) henüz. –

+0

PostgreSQL ile, henüz herhangi bir bağlantı kesme işlemi gerçekleştiremedik. –

+0

Yani - try/catch/retry mantığını kabul etmeye karar verdiniz mi? ORM sınıfımızda onlarca sorgu fonksiyonumuz var ve birkaç düzinelerce sınıfı yönetiyoruz. Bu gerçekten ekliyor. BTW - biz Postgres RHEL oom katili uzun süren bir postmaster öldürdü geçenlerde ne zamana kadar yeniden başlatmayı ile herhangi bir sorun olmamıştı. Aniden, bu zarafetten kurtulmamız gerektiğini farkettik. – user590028

cevap

6

Burası bir lambda veya kapatılmasıyla tüm veritabanı kodudur yaklaşım ve yardımcı fonksiyonu içine geçmek gibi bir yol kullandığınızdan emin bağlantı kesme özel durumunu yakalamak ve yeniden dener. Yani örnek ile

: Yalnızca bir okuma yaptığını nerede durumun ele alınması run_query içine bir boole geçirerek bu daha süslü hale ve bu nedenle geri alma olmadan yeniden denemek istiyor olabilir

import sqlalchemy as SA 

def main(): 
    def query(): 
     for name in session.query(Names): 
      print name 

    run_query(query) 

def run_query(f, attempts=2): 
    while attempts > 0: 
     attempts -= 1 
     try: 
      return f() # "break" if query was successful and return any results 
     except SA.exc.DBAPIError as exc: 
      if attempts > 0 and exc.connection_invalidated: 
       session.rollback() 
      else: 
       raise 

.

Bu, DRY ilkesini karşılamanıza yardımcı olur, çünkü yeniden deneme ve geri alma işlemlerini yönetmek için kullanılan tüm çirkin kazan plakaları tek bir konuma yerleştirilir.

+0

Bu mükemmel bir çözüm! Paylaşım için teşekkürler. – user590028

+0

Bu iyi bir çözümdür, ancak şimdi SQL Alchemy belgelerine göz atıyorum. Bunun yerine, her sorguya, run_query uygulamasına geçmek yerine, otomatik olarak her bir sorguya uygulanıp uygulanamayacağını görmek istiyorum. – Mark

İlgili konular