2014-04-11 12 views
5

Tech ParticolareGolang - pgbouncer e l'uso delle transazioni

  • versione 1.2 go
  • biblioteca postrgres per go bmizerany/pq

Questo problema mi sta facendo impazzire e spero che qualcuno sarà in grado di aiutare.

Ho sviluppato un'applicazione in golang per leggere i dati da un database postgres e per ogni record effettuare una richiesta http e quindi aggiornare il database.

Questo è tutto abbastanza semplice. Tuttavia, abbiamo pgbouncer sul posto. La configurazione che abbiamo per pgbouncer è tale che non supporta le istruzioni preparate. Vai silenziosamente a tutte le query in una dichiarazione preparata. Il modo per aggirare questo per pgbouncer è impostare una transazione. Questo va bene per cose come insert/update/delete.

Nel caso della dichiarazione prescelta che sto avvolgendolo in transazione:

func TransactionQuery(db *sql.DB, baseQuery string) (rows *sql.Rows, code int, err error) { 
     tx, txErr := db.Begin() 
     if txErr != nil { 
      return nil, -1, txErr 
     } 

     selectStmt, prepErr := tx.Prepare(baseQuery) 
     if prepErr != nil { 
      return nil, -1, fmt.Errorf("Failed to prepare statment: %s Error: %v", baseQuery, prepErr) 
     } 

     defer func() { 
      if stmtErr := selectStmt.Close(); stmtErr != nil { 
       rows = nil 
       code = -2 
       err = fmt.Errorf("Failed to close statement: %v.", stmtErr) 
      } 
     }() 

     rows, err = selectStmt.Query() 
     if err != nil { 
      fmt.Errorf("Failed to retrieve data: %v", err) 
      return nil, -1, err 
     } 
     return rows, 0, nil 
    } 

(hhmm, che sembra avere gettare il rientro fuori un po ') AsS potete vedere sto iniziando BNUT non di chiusura la transazione. Ciò causa un problema nel lato pg delle cose in cui ogni selezione viene lasciata in uno stato "inattivo nella transazione"

Ho provato tx.Commit() e tx.Rollback() e in entrambi i casi ottengo errori:

"unknown response for simple query '3'" 

o

"unknown response for simple query 'D'" 

ho chiudo con successo l'operazione in Go? Spero di ottenere i nostri pgbouncer.ini aggiornati per permettere a me di passare a lib/pq per la libreria conducente ma io non sono sicuro che questo aiuterà direttamente questo problema.

Quindi, come posso chiudere correttamente l'oggetto tx o c'è un modo per forzare Vai a non usare istruzioni preparate sotto il cofano?

Grazie Nathan

ho cercato di cambiare le cose un po ':

func TransactionQuery(db *sql.DB, baseQuery string) (rows *sql.Rows, code int, err error) { 
    tx, txErr := db.Begin() 
    if txErr != nil { 
     return nil, -1, txErr 
    } 

    /*selectStmt, prepErr := tx.Prepare(baseQuery) 
     if prepErr != nil { 
      return nil, -1, fmt.Errorf("Failed to prepare statment: %s Error: %v", baseQuery, prepErr) 
     } 
    */ 
    rows, err = tx.Query(baseQuery) 
    if err != nil { 
     fmt.Errorf("Failed to retrieve data: %v", err) 
     return nil, -1, err 
    } 

    /* if stmtErr := selectStmt.Close(); stmtErr != nil { 
      rows = nil 
      code = -2 
      err = fmt.Errorf("Failed to close statement: %v.", stmtErr) 
     }*/ 

    if txCloseErr := tx.Commit(); txErr != nil { 
     rows = rows 
     code = -3 
     err = txCloseErr 
    } 
    return rows, 0, nil 
} 

Quello che vedo nei log con questo codice:

pq: unexpected describe rows response: '3' 

Tuttavia, dovrei Fai notare che questo è quando provi una dichiarazione di selezione per la seconda volta. Questa applicazione seleziona un batch, lo gestisce e seleziona un batch successivo. Questo errore si verifica nella seconda selezione. Non ci sono problemi con la prima selezione.

+0

C'è qualcosa nel registro Postgres? Qui possono essere registrate dichiarazioni problematiche che ti permetteranno di vedere se ciò che pensi venga inviato è effettivamente ricevuto dal db. –

+0

Devo chiedere al team DBA per quello che non ho accesso a quei registri. È interessante notare che, se lascio la transazione inclusa, l'app viene eseguita come previsto, ma blocca il pgbouncer con lo stato di inattività nello stato della transazione. – nathj07

risposta

2

Per chiunque altro che ha colpito questo ho risolto questo.

Il codice che avevo stava restituendo l'oggetto righe al codice chiamante (non mostrato) sopra. La chiusura della transazione prima della lettura delle righe sembrava essere la causa del problema. Non capisco perché, quindi, per favore, chiarisci se lo fai.

Ora restituisco sia le righe che l'oggetto della transazione.Quindi, quando ho letto tutte le righe, eseguo il rollback della transazione. questo mantiene tutto funzionante.

Grazie Nathan

+1

Quando "COMMIT" la transazione, stai dicendo a pgbouncer che può riciclare il backend per un'altra transazione. 'BEGIN', query, read rows,' COMMIT'/'ROLLBACK'. – Sean

0

Tx.Query restituisce un'istanza di sql.Rows, che è un cursore per il set di risultati. I dati non sono stati necessariamente recuperati mentre si sta iterando questo cursore. La transazione deve rimanere aperta mentre si sta iterando il cursore.

Questo è il motivo per cui non è più possibile ripetere il cursore una volta chiusa la transazione.

Problemi correlati