2010-06-28 218 views
3

我正在运行一堆使用Python和psycopg2的查询。我创建了一个有大约200万行的大型临时表,然后通过使用cur.fetchmany(1000)从中一次获得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() s,但是我删除了所有创建的临时表,而且我对每个“扩展”事务只触摸相同的5个表,所以我没有看看如何用完桌面锁可能是问题...

回答

0

那么,你是否正在一个事务中运行整个create +查询?这也许可以解释这个问题。仅仅因为它发生在你放弃表时并不一定意味着任何事情,这可能恰好是自由锁用完的时刻。

使用视图可能是临时表的替代方法,如果您创建了这个东西,然后立即删除它,肯定会由我的第一个选择。

+0

交易如何转换为游标和.commits?我没有做任何.commits,但我正在使用新的游标进行查询 – Claudiu 2010-06-28 14:48:49

2

当你创建一个表时,你会得到一个持续到事务结束的排它锁。即使你继续放下它。

所以,如果我开始TX和创建临时表:

[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) 

事实上,它增加两个更多的锁......看起来,如果我不断创建/删除临时表,它会每次添加3个锁。

所以我想一个答案是,你将需要足够的锁来应付所有这些表在整个交易中被添加/删除。或者,您可以尝试在查询之间重新使用临时表,只需截断它们以删除所有临时数据?

2

您是否创建了多个具有相同名称的保存点而不释放它们?

我跟着these instructions,反复执行 SAVEPOINT savepoint_name但是从未执行任何对应的RELEASE SAVEPOINT savepoint_name语句。 PostgreSQL只是掩盖旧的保存点,从来没有释放它们。它跟踪每一个,直到锁内存不足。我认为我的postgresql内存限制要低得多,只需要约10,000个保存点就可以达到max_locks_per_transaction