postgresql: fuera de la memoria compartida?

Estoy ejecutando un montón de consultas usando Python y psycopg2. Creo una gran tabla temporal con aproximadamente 2 millones de filas, luego obtengo 1000 filas a la vez utilizando cur.fetchmany(1000) y ejecuto consultas más extensas relacionadas con esas filas. Sin embargo, las consultas extensas son autosuficientes: una vez que terminan, ya no necesito sus resultados cuando pase a las siguientes 1000.

Sin embargo, alrededor de 1000000 filas, obtuve una excepción de psycopg2:

 psycopg2.OperationalError: out of shared memory HINT: You might need to increase max_locks_per_transaction. 

Curiosamente, esto sucedió cuando estaba ejecutando una consulta para eliminar algunas tablas temporales que crearon las consultas más extensas.

¿Por qué podría pasar esto? Hay alguna manera de evitarlo? Fue molesto que esto sucediera a mitad de camino, lo que significa que tengo que correr todo de nuevo. ¿Qué podría tener que ver max_locks_per_transaction con cualquier cosa?

NOTA: No estoy haciendo ningún .commit() s, pero estoy eliminando todas las tablas temporales que creo, y solo estoy tocando las mismas 5 tablas de todas las transacciones “extensas”, así que no veo cómo quedarse sin lockings de mesa podría ser el problema …

cuando creas una tabla, obtienes un locking exclusivo que dura hasta el final de la transacción. Incluso si luego sigues adelante y lo dejas caer.

Así que si comienzo un tx y creo una tabla temporal:

 steve@steve@[local] *=# create temp table foo(foo_id int); CREATE TABLE steve@steve@[local] *=# select * from pg_locks where pid = pg_backend_pid(); locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted ---------------+----------+-----------+------+-------+------------+---------------+---------+-----------+----------+--------------------+-------+---------------------+--------- virtualxid | | | | | 2/105315 | | | | | 2/105315 | 19098 | ExclusiveLock | t transactionid | | | | | | 291788 | | | | 2/105315 | 19098 | ExclusiveLock | t relation | 17631 | 10985 | | | | | | | | 2/105315 | 19098 | AccessShareLock | t relation | 17631 | 214780901 | | | | | | | | 2/105315 | 19098 | AccessExclusiveLock | t object | 17631 | | | | | | 2615 | 124616403 | 0 | 2/105315 | 19098 | AccessExclusiveLock | t object | 0 | | | | | | 1260 | 16384 | 0 | 2/105315 | 19098 | AccessShareLock | t (6 rows) 

Estos lockings de “relación” no se eliminan cuando suelto la tabla:

 steve@steve@[local] *=# drop table foo; DROP TABLE steve@steve@[local] *=# select * from pg_locks where pid = pg_backend_pid(); locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted ---------------+----------+-----------+------+-------+------------+---------------+---------+-----------+----------+--------------------+-------+---------------------+--------- virtualxid | | | | | 2/105315 | | | | | 2/105315 | 19098 | ExclusiveLock | t object | 17631 | | | | | | 1247 | 214780902 | 0 | 2/105315 | 19098 | AccessExclusiveLock | t transactionid | | | | | | 291788 | | | | 2/105315 | 19098 | ExclusiveLock | t relation | 17631 | 10985 | | | | | | | | 2/105315 | 19098 | AccessShareLock | t relation | 17631 | 214780901 | | | | | | | | 2/105315 | 19098 | AccessExclusiveLock | t object | 17631 | | | | | | 2615 | 124616403 | 0 | 2/105315 | 19098 | AccessExclusiveLock | t object | 17631 | | | | | | 1247 | 214780903 | 0 | 2/105315 | 19098 | AccessExclusiveLock | t object | 0 | | | | | | 1260 | 16384 | 0 | 2/105315 | 19098 | AccessShareLock | t (8 rows) 

De hecho, agregó dos lockings más … Parece que si continuamente creo / suelto esa tabla temporal, agrega 3 lockings cada vez.

Entonces, supongo que una respuesta es que necesitará suficientes lockings para hacer frente a todas estas tablas que se agregan / eliminan a lo largo de la transacción. Alternativamente, podría intentar reutilizar las tablas temporales entre consultas, simplemente truncarlas para eliminar todos los datos temporales.

¿Creaste múltiples puntos de guardado con el mismo nombre sin soltarlos?

Seguí estas instrucciones , ejecutando repetidamente SAVEPOINT savepoint_name pero sin ejecutar nunca ninguna instrucción correspondiente RELEASE SAVEPOINT savepoint_name . PostgreSQL solo estaba ocultando los antiguos puntos de salvaguarda, nunca liberándolos. Realizó un seguimiento de cada uno hasta que se quedó sin memoria para los lockings. Creo que mis límites de memoria postgresql eran mucho más bajos, solo me tomaron ~ 10,000 puntos de guardado para que golpee max_locks_per_transaction .

Bueno, ¿está ejecutando todas las consultas de creación + dentro de una sola transacción? Esto quizás explique el problema. El hecho de que sucediera cuando se estaban eliminando las tablas no significaba necesariamente nada, ese podría ser el punto en el que se agotaron los lockings libres.

El uso de una vista podría ser una alternativa a una tabla temporal y, definitivamente, sería mi primera elección si está creando esta cosa y luego la elimina de inmediato.