¿Las transacciones en PostgreSQL a través de `psycopg2` son por cursor o por conexión?


10

Estoy trabajando con PostgreSQL 9.3 usando la psycopg2API de la base de datos.

Tengo la API DB configurada en el nivel de aislamiento mínimo (modo "autocompromiso") y estoy administrando mis propias transacciones directamente a través de SQL. Ejemplo:

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

Básicamente, ¿la transacción que se inicia está cur.execute("BEGIN;")limitada solo a ese cursor, o es para toda la conexión ( self.conn.cursor())?

Algunas de las cosas más complejas que estoy haciendo involucran múltiples operaciones de base de datos separadas, que lógicamente divido en funciones. Como todo esto está en una clase que tiene la conexión como miembro, es mucho más conveniente crear cursores dentro de cada función. Sin embargo, no estoy seguro de cómo funciona la creación de cursores dentro de una transacción.

Básicamente, si las transacciones son por conexión, puedo crear muchos cursores sobre la marcha dentro de la transacción. Si son por cursor, eso significa que tengo que pasar el cursor por todas partes. Cual es

La documentación no toca esto, aunque el hecho de que pueda llamar connection.commit()me hace confiar bastante en que el control de la transacción es por conexión.

Respuestas:


7

Las transacciones son por sesión, es decir, por conexión.

PostgreSQL no admite la suspensión y reanudación de transacciones, por lo que psycopg2 no podría hacerlas por cursor a menos que implícitamente creara nuevas conexiones detrás de escena.

En la práctica no encuentro los cursores de psycopg2 particularmente útiles. Pueden retener conjuntos de resultados si no está utilizando la recuperación incremental del servidor, pero no los considero buenos para mucho más.

¿Por qué emitir manualmente beginy commitsin embargo, en lugar de utilizar los métodos de conexión para ellos?


AFICT de la documentación, todo el modelo "DB API" realmente no admite transacciones explícitas en absoluto.
Nombre falso el

1
@FakeName No tiene que hacerlo explícitamente begin. Si no hay ninguna transacción abierta, se inicia una nueva para usted. Solo debes commitdelinear las transacciones. Así que sí, el modelo DB-API hace de soporte transacciones explícitas.
Craig Ringer

1
Si la API de DB lo hace automáticamente sin que yo lo indique específicamente, es un comienzo implícito . Y además, es irrelevante, ya que (como dije en la pregunta), estoy usando el modo de confirmación automática, porque no quiero esas BEGINdeclaraciones automáticas . No quiero psycopg2crear una nueva transacción para cada uno SELECT.
Nombre falso el

TL; DR básicamente quiero saber el alcance exacto de todas las transacciones que ocurren porque A. Estoy loco de esa manera, y B. ayuda mucho con la depuración.
Nombre falso el

1
No me sorprendería ver errores extraños apareciendo con esto. La confirmación automática de AFAIK está destinada a ser una confirmación automática, no una gestión manual de transacciones. Si realmente desea administrar manualmente los ámbitos de transacción, un extra BEGINes inofensivo y PostgreSQL simplemente lo ignorará WARNING: there is already a transaction in progress.
Craig Ringer

1

De la documentación de psycopg2 :

En Psycopg, las transacciones son manejadas por la clase de conexión. Por defecto, la primera vez que se envía un comando a la base de datos (utilizando uno de los cursores creados por la conexión), se crea una nueva transacción. Los siguientes comandos de la base de datos se ejecutarán en el contexto de la misma transacción, no solo los comandos emitidos por el primer cursor, sino los emitidos por todos los cursores creados por la misma conexión. Si algún comando falla, la transacción se cancelará y no se ejecutará ningún otro comando hasta que se llame al método rollback ().

Al mismo tiempo, desde la versión 2.4.2, existe el autocommitatributo (énfasis agregado):

Atributo de lectura / escritura: si Trueel controlador no maneja ninguna transacción y cada declaración enviada al backend tiene efecto inmediato; si False se inicia una nueva transacción en la primera ejecución del comando : los métodos commit()o se rollback()deben invocar manualmente para finalizar la transacción.

El modo de confirmación automática es útil para ejecutar comandos que requieren ejecutarse fuera de una transacción, como CREATE DATABASEo VACUUM.

El valor predeterminado es False(confirmación manual) según la especificación DBAPI.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.