As transações no PostgreSQL são via `psycopg2` por cursor ou por conexão?

10

Estou trabalhando com o PostgreSQL 9.3 usando a psycopg2API do banco de dados.

Eu tenho a API do banco de dados definida no nível mínimo de isolamento (modo "confirmação automática") e estou gerenciando minhas próprias transações diretamente via SQL. Exemplo:

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;")

Basicamente, a transação iniciada pelo cur.execute("BEGIN;")limitado a apenas esse cursor ou é para toda a conexão ( self.conn.cursor())?

Algumas das coisas mais complexas que estou fazendo envolvem várias operações separadas do banco de dados, que eu logicamente decomponho em funções. Como tudo isso é de uma classe que tem a conexão como membro, é muito mais conveniente criar cursores dentro de cada função. No entanto, não tenho certeza de como funciona a criação de cursores em uma transação.

Basicamente, se as transações são por conexão, posso criar muitos cursores dinamicamente dentro da transação. Se eles são por cursor, isso significa que eu tenho que passar o cursor por toda parte. Qual é?

A documentação não aborda isso, embora o fato de você poder ligar connection.commit()me deixe bastante confiante de que o controle de transações é por conexão.

Nome falso
fonte

Respostas:

7

As transações são por sessão, ou seja, por conexão.

O PostgreSQL não suporta a suspensão e a retomada de transações, portanto, o psycopg2 não poderia torná-las por cursor, a menos que implicitamente crie novas conexões nos bastidores.

Na prática, não acho os cursores do psycopg2 particularmente úteis. Eles podem reter conjuntos de resultados se você não estiver usando a busca incremental do servidor, mas eu não os acho bons para muito mais.

Por que emitir manualmente begine commit, em vez de usar os métodos de conexão para eles?

Craig Ringer
fonte
AFICTO da documentação, todo o modelo "DB API" não suporta realmente transações explícitas.
Fake Name
11
@FakeName Você não precisa explicitamente begin. Se nenhuma transação estiver aberta, uma nova será iniciada para você. Você apenas commitdelineia transações. Então, sim, o modelo DB-API faz transações explícitas de apoio.
Craig Ringer
11
Se a API do DB estiver fazendo isso automaticamente, sem que eu o direcione especificamente, isso é um começo implícito . Além disso, é irrelevante, pois (como afirmei na pergunta), estou usando o modo de confirmação automática, porque não quero essas BEGINdeclarações automáticas . Não quero psycopg2criar uma nova transação para cada uma SELECT.
Fake Name
TL; DR basicamente, eu quero saber o escopo exato de todas as transações acontecendo porque A. sou louco dessa maneira e B. ajuda muito na depuração.
Fake Name
11
Eu não ficaria surpreso ao ver bugs estranhos aparecendo com isso. A confirmação automática do AFAIK deve ser realmente a confirmação automática, não o gerenciamento manual de transações. Se você realmente deseja gerenciar manualmente os escopos de transação, um extra BEGINé inofensivo e será apenas ignorado pelo PostgreSQL WARNING: there is already a transaction in progress.
Craig Ringer
1

Na documentação do psycopg2 :

No Psycopg, as transações são tratadas pela classe de conexão. Por padrão, na primeira vez que um comando é enviado ao banco de dados (usando um dos cursores criados pela conexão), uma nova transação é criada. Os seguintes comandos do banco de dados serão executados no contexto da mesma transação - não apenas os comandos emitidos pelo primeiro cursor, mas os emitidos por todos os cursores criados pela mesma conexão. Se algum comando falhar, a transação será abortada e nenhum comando adicional será executado até uma chamada ao método rollback ().

Ao mesmo tempo, da versão 2.4.2, existe o autocommitatributo (ênfase adicionada):

Atributo de leitura / gravação: se Truenenhuma transação for manipulada pelo driver e todas as instruções enviadas para o back-end terão efeito imediato; se False uma nova transação for iniciada na primeira execução do comando : os métodos commit()ou rollback()devem ser invocados manualmente para finalizar a transação.

O modo de confirmação automática é útil para executar comandos que precisam ser executados fora de uma transação, como CREATE DATABASEou VACUUM.

O padrão é False(confirmação manual) conforme a especificação DBAPI.

Stephen
fonte