2010-06-28 6 views
3

Я запускаю кучу запросов с использованием Python и psycopg2. Я создаю одну большую временную таблицу с примерно 2 миллионами строк, затем я получаю по 1000 строк за раз с помощью cur.fetchmany(1000) и запускаю более обширные запросы с участием этих строк. Обширные запросы являются самодостаточными, хотя, когда они закончены, мне больше не нужны их результаты, когда я перехожу к следующему 1000.postgresql: из общей памяти?

Однако, около 1000000 строк, я получил исключение из psycopg2:

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

Как ни странно, это произошло, когда я выполнял запрос, чтобы удалить некоторые временные таблицы, которые создавали более сложные запросы.

Почему это может случиться? Есть ли способ избежать этого? Было досадно, что это произошло на полпути, а это значит, что я должен снова запустить все это. Что могло бы быть max_locks_per_transaction?

ПРИМЕЧАНИЕ: Я не делаю никаких .commit(), но я удаляю все временные таблицы, которые я создаю, и я касаюсь только тех же 5 таблиц в любом случае для каждой «обширной» транзакции, поэтому я не посмотрите, как может возникнуть проблема с запуском столовых замков ...

ответ

0

Ну, вы запускаете все творения + запросы внутри одной транзакции? Возможно, это объяснит проблему. Просто потому, что это произошло, когда вы отбрасывали таблицы, это не обязательно означало бы что-либо, что может случиться так, что когда закончились свободные блокировки.

Использование представления может быть альтернативой временной таблице и, безусловно, с помощью моего первого выбора, если вы создаете эту вещь, а затем сразу же удаляете ее.

+0

Как транслировать транзакции курсоров и .commits? Я не делал никаких команд, но я использовал новые курсоры для запросов – Claudiu

2

При создании таблицы вы получаете эксклюзивную блокировку, которая длится до конца транзакции. Даже если вы идите вперед и опустите его.

Так что, если я начну ТХ и создать временную таблицу:

[email protected]@[local] *=# create temp table foo(foo_id int); 
CREATE TABLE 
[email protected]@[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) 

Эти замки «отношение» не упал, когда я падаю на стол:

[email protected]@[local] *=# drop table foo; 
DROP TABLE 
[email protected]@[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) 

На самом деле, он добавил еще два замка ... Кажется, что если я постоянно создаю/удаляю эту временную таблицу, она добавляет по три замка каждый раз.

Таким образом, я думаю, что один ответ заключается в том, что вам понадобятся достаточно блокировок, чтобы справиться со всеми этими таблицами, которые добавляются/удаляются в течение всей транзакции. В качестве альтернативы вы можете попытаться повторно использовать временные таблицы между запросами, просто усечь их, чтобы удалить все временные данные?

2

Вы создали несколько точек сохранения с тем же именем, не отпуская их?

Я следовал за these instructions, многократно исполняя SAVEPOINT savepoint_name, но без выполнения каких-либо соответствующих заявлений RELEASE SAVEPOINT savepoint_name. PostgreSQL просто маскировал старые точки сохранения, не освобождая их. Он следил за каждым, пока у него не осталось памяти для замков. Я думаю, что мои пределы памяти postgresql были намного ниже, для меня потребовалось ~ 10 000 точек сохранения, чтобы нанести удар max_locks_per_transaction.

Смежные вопросы