2009-08-02 2 views
18

Im giocherellare con psycopg2 e mentre c'è un .commit() e .rollback() non c'è .begin() o simili per avviare una transazione, o così sembra? mi aspetto di essere in grado di fareCome si eseguono transazioni di database con psycopg2/python db api?

db.begin() # possible even set the isolation level here 
curs = db.cursor() 
cursor.execute('select etc... for update') 
... 
cursor.execute('update ... etc.') 
db.commit(); 

Quindi, come le transazioni funzionano con psycopg2? Come impostare/modificare il livello di isolamento?

risposta

23

Utilizzare db.set_isolation_level(n), supponendo che db sia l'oggetto di connessione. Come Federico ha scritto here, il significato di n è:

0 -> autocommit 
1 -> read committed 
2 -> serialized (but not officially supported by pg) 
3 -> serialized 

Come documentato here, psycopg2.extensions ti dà costanti simboliche per lo scopo:

Setting transaction isolation levels 
==================================== 

psycopg2 connection objects hold informations about the PostgreSQL `transaction 
isolation level`_. The current transaction level can be read from the 
`.isolation_level` attribute. The default isolation level is ``READ 
COMMITTED``. A different isolation level con be set through the 
`.set_isolation_level()` method. The level can be set to one of the following 
constants, defined in `psycopg2.extensions`: 

`ISOLATION_LEVEL_AUTOCOMMIT` 
    No transaction is started when command are issued and no 
    `.commit()`/`.rollback()` is required. Some PostgreSQL command such as 
    ``CREATE DATABASE`` can't run into a transaction: to run such command use 
    `.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)`. 

`ISOLATION_LEVEL_READ_COMMITTED` 
    This is the default value. A new transaction is started at the first 
    `.execute()` command on a cursor and at each new `.execute()` after a 
    `.commit()` or a `.rollback()`. The transaction runs in the PostgreSQL 
    ``READ COMMITTED`` isolation level. 

`ISOLATION_LEVEL_SERIALIZABLE` 
    Transactions are run at a ``SERIALIZABLE`` isolation level. 


.. _transaction isolation level: 
    http://www.postgresql.org/docs/8.1/static/transaction-iso.html 
+0

Bello. L'impostazione predefinita è autocommit? Quando si imposta n = 1,2 o 3 cosa inizia una transazione? Creazione di un nuovo cursore o solo di tutte le operazioni sul db dall'ultimo commit/rollback? – Leeeroy

+0

L'autocommit è l'impostazione predefinita nella maggior parte dei DBMS. –

+1

Alex ha aggiunto più cose dopo che ho chiesto. E dice READ_COMMITED è l'impostazione predefinita per psycopg2 – Leeeroy

5

preferisco vedere in modo esplicito dove le mie transazioni sono:

  • cursor.execute ("BEGIN")
  • cursore
  • .execute ("COMMIT")
+2

È attivato o disattivato l'autocommit? Confonderà Psycopg2 o altri moduli di database? La gestione delle transazioni di ODBC utilizza un approccio simile all'API python DB e ho notato espliciti * non * per usare comandi di gestione delle transazioni SQL che sovvertono l'interfaccia ODBC (ad esempio http://msdn.microsoft.com/en-us/ biblioteca/ms131281.aspx). –

+1

Si prega di non farlo. Combatterai contro la funzionalità di autocommit, non c'è alcuna garanzia che il risultato sarà bello. –

+2

È con autocommit OFF. – peufeu

12

Il BEGIN con API DB standard python è sempre implicito. Quando si inizia a lavorare con il database, il driver emette un BEGIN e dopo un qualsiasi COMMIT o ROLLBACK viene emesso un altro BEGIN. Un'API DB python conforme alle specifiche dovrebbe sempre funzionare in questo modo (non solo il postgresql).

È possibile modificare questa impostazione del livello di isolamento in autocommit con db.set_isolation_level(n) come indicato da Alex Martelli.

Come ha detto Tebas, l'inizio è implicito ma non eseguito fino a quando non viene eseguito un SQL, quindi se non si esegue alcun SQL, la sessione non è in una transazione.

+2

È vero? Credo che dopo una chiamata di commit() o rollback() ci sia _non_ invia un altro BEGIN immediatamente - viene inviato implicitamente con il prossimo execute(). Dopo un commit()/rollback() la connessione è in stato 'idle' piuttosto che 'idle in transaction'. – Tebas

+0

Dopo un commit()/rollback() la connessione è in stato 'idle'. L'API Python DB invierà un altro BEGIN solo dopo un altro execute() in modo da non creare un deadlock se il tuo programma non finisce mai. Per riepilogare una volta che chiamate execute() dovreste commit() o rollback() se no il vostro programma sarà "idle in transaction". – praveenak

Problemi correlati