postgresql: из общей памяти?

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

Тем не менее, около 1000000 строк, я получил исключение из psycopg2:

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

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

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

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

3 ответа

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

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

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)

Эти "отношения" блокировки не удаляются, когда я отбрасываю таблицу:

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)

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

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

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

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

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

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

Другие вопросы по тегам