2015-04-14 19 views
14

Abbiamo sperimentato la gestione della disconnessione di sqlalchemy e come si integra con ORM. Abbiamo studiato i documenti e il consiglio sembra essere quello di intercettare l'eccezione di disconnessione, emettere un rollback() e riprovare il codice.Un migliore approccio alla gestione di sqlalchemy disconnette

esempio:

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 

Seguo la logica - è necessario ritirare ogni transazioni attive e riprodurre loro per garantire un ordinamento coerente delle vostre azioni.

MA - questo significa un sacco di codice aggiuntivo aggiunto a ogni funzione che desidera lavorare con i dati. Inoltre, nel caso di SELECT, non stiamo modificando i dati e il concetto di rollback/ri-richiesta non è solo antiestetico, ma una violazione del principio di DRY (non ripeterti).

Mi chiedevo se agli altri sarebbe dispiaciuto condividere come gestiscono le disconnessioni con sqlalchemy.

FYI: stiamo usando sqlalchemy 0.9.8 e 9.2.9 Postgres

+1

Attualmente stiamo usando [Pessimistic Disconnect Handling] (http://docs.sqlalchemy.org/en/latest/core/pooling.pooling.php?disconnect-handling-pessimistic) con * un po '* di successo per mitigare 'MySQL ha andato via '. Stiamo ancora assistendo a un caso in produzione, anche se non riusciamo a recuperare da quella situazione e la transazione non può essere ripristinata e si blocca. Anche se questo potrebbe avere qualcosa a che fare con il fatto che stiamo unendo due transazioni (ZODB e SQL) e non stiamo usando [commit a due fasi] (http://docs.sqlalchemy.org/en/latest/orm/ session_transaction.html # enable-two-phase-commit) ancora. –

+0

Con PostgreSQL, semplicemente non abbiamo ancora avuto alcun problema di disconnessione, quindi nessuna esperienza lì. –

+0

Quindi, hai deciso di accettare la logica try/catch/retry? Abbiamo decine di funzioni di query nella nostra classe ORM e gestiamo diverse classi di dozzine. Questo davvero aggiunge. A proposito, non abbiamo avuto alcun problema con Postgres che ha riavviato fino a poco tempo fa quando l'assassino di RHEL ha ucciso un postmaster di vecchia data. Improvvisamente ci siamo resi conto che dobbiamo riprenderci da questo con grazia. – user590028

risposta

6

Il modo in cui mi piace di affrontare questo è il posto tutto il mio codice del database in un lambda o la chiusura, e passare che in una funzione di supporto che gestirà l'intercettazione dell'eccezione di disconnessione e riprovando.

Quindi, con il tuo esempio:

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 

È possibile rendere questo più fantasia passando un valore booleano in run_query per gestire il caso in cui si sta solo facendo una lettura, e quindi vogliono riprovare, senza rollback.

Questo consente di soddisfare il principio ASCIUTTO poiché tutto il brutto codice di piastra di caldaia per la gestione di tentativi + rollback viene posizionato in un'unica posizione.

+0

Questa è una soluzione eccellente! Grazie per la condivisione. – user590028

+0

Questa è una buona soluzione, ma ora sto studiando i documenti di Alchemy SQL per vedere se questo può essere applicato automaticamente ad ogni query piuttosto che doverlo passare in run_query. – Mark

Problemi correlati