Le transazioni in PostgreSQL sono `psycopg2` per cursore o per connessione?


10

Sto facendo un po 'di lavoro con PostgreSQL 9.3 usando l' psycopg2API del database.

Ho impostato l'API DB nel livello di isolamento minimo (modalità "autocommit") e gestisco le mie transazioni direttamente tramite SQL. Esempio:

cur = self.conn.cursor()
cur.execute("BEGIN;")
cur.execute("SELECT dbId, downloadPath, fileName, tags FROM {tableName} WHERE dlState=%s".format(tableName=self.tableName), (2, ))
ret = cur.fetchall()
cur.execute("COMMIT;")

Fondamentalmente, la transazione che viene avviata è cur.execute("BEGIN;")limitata al solo cursore o è per l'intera connessione ( self.conn.cursor())?

Alcune delle cose più complesse che sto facendo riguardano più operazioni separate di database, che logicamente suddivido in funzioni. Poiché questo è tutto in una classe che ha la connessione come membro, è molto più conveniente creare cursori all'interno di ciascuna funzione. Tuttavia, non sono sicuro di come funzioni la creazione di cursori all'interno di una transazione.

Fondamentalmente, se le transazioni sono per connessione, posso semplicemente creare molti cursori al volo all'interno della transazione. Se sono per cursore, significa che devo passare il cursore ovunque. Cos'è questo?

La documentazione non tocca questo, sebbene il fatto che tu possa chiamare connection.commit()mi rende abbastanza sicuro che il controllo delle transazioni è per connessione.

Risposte:


7

Le transazioni sono per sessione, ovvero per connessione.

PostgreSQL non supporta la sospensione e la ripresa delle transazioni, quindi psycopg2 non può renderle per cursore a meno che non crei implicitamente nuove connessioni dietro le quinte.

In pratica non trovo particolarmente utili i cursori di psycopg2. Possono conservare i set di risultati se non si utilizza il recupero incrementale dal server, ma non li trovo utili per molto altro.

Perché emettere manualmente begine commit, invece di utilizzare i metodi di connessione per loro?


AFICT dalla documentazione, l'intero modello "DB API" non supporta affatto le transazioni esplicite.
Nome falso

1
@FakeName Non è necessario esplicitamente begin. Se nessuna transazione è aperta, ne viene avviata una nuova. Devi solo commitdelineare le transazioni. Quindi sì, il modello DB-API fa supporto transazioni esplicite.
Craig Ringer

1
Se l'API DB lo sta facendo automaticamente senza che io lo abbia specificamente indirizzato a farlo, è un inizio implicito . E inoltre, è irrilevante, poiché (come ho affermato nella domanda), sto usando la modalità autocommit, perché non voglio quelle BEGINdichiarazioni automatiche . Non voglio psycopg2creare una nuova transazione per ciascuno SELECT.
Nome falso

TL; DR fondamentalmente voglio conoscere la portata esatta di tutte le transazioni in corso perché A. Sono pazzo in quel modo e B. aiuta molto nel debugging.
Nome falso

1
Non sarei sorpreso di vedere strani bug spuntare con questo. L'autocommit AFAIK è davvero pensato per essere autocommit e non gestione manuale delle transazioni. Se vuoi davvero gestire manualmente gli ambiti delle transazioni, un extra BEGINè innocuo e verrà semplicemente ignorato da PostgreSQL con WARNING: there is already a transaction in progress.
Craig Ringer

1

Dalla documentazione psycopg2 :

In Psycopg le transazioni sono gestite dalla classe di connessione. Per impostazione predefinita, la prima volta che un comando viene inviato al database (utilizzando uno dei cursori creati dalla connessione), viene creata una nuova transazione. I seguenti comandi del database verranno eseguiti nel contesto della stessa transazione - non solo i comandi emessi dal primo cursore, ma quelli emessi da tutti i cursori creati dalla stessa connessione. In caso di errore di un comando, la transazione verrà interrotta e nessun ulteriore comando verrà eseguito fino a quando una chiamata al metodo rollback ().

Allo stesso tempo, dalla versione 2.4.2, c'è l' autocommitattributo (enfasi aggiunta):

Attributo di lettura / scrittura: se Trueil conducente non gestisce alcuna transazione e ogni istruzione inviata al back-end ha effetto immediato; se False una nuova transazione viene avviata al primo comando : i metodi commit()o rollback()devono essere richiamati manualmente per terminare la transazione.

La modalità autocommit è utile per eseguire comandi che richiedono di essere eseguiti al di fuori di una transazione, come CREATE DATABASEo VACUUM.

L'impostazione predefinita è False(commit manuale) come da specifica DBAPI.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.