Cla*_*diu 4 python database postgresql psycopg2
我正在使用 Python 和 psycopg2 运行一堆查询。我创建了一个包含大约 200 万行的大型临时表,然后通过使用cur.fetchmany(1000)和运行涉及这些行的更广泛的查询,一次从中获取 1000行。但是,广泛的查询是自给自足的 - 一旦完成,当我继续下一个 1000 时,我不再需要它们的结果。
但是,在大约 1000000 行中,我从 psycopg2 中得到了一个例外:
psycopg2.OperationalError: out of shared memory
HINT: You might need to increase max_locks_per_transaction.
Run Code Online (Sandbox Code Playgroud)
有趣的是,这发生在我执行查询以删除更广泛的查询创建的一些临时表时。
为什么会发生这种情况?有什么办法可以避免吗?这很烦人,这发生在中途,这意味着我必须再次运行它。可能max_locks_per_transaction有什么关系?
注意:我没有做任何.commit()s,但我正在删除我创建的所有临时表,而且我只为每个“广泛”事务处理相同的 5 个表,所以我不知道如何用完表锁可能是问题...
当你创建一个表时,你会得到一个排他锁,这个锁一直持续到事务结束。即使你继续前进并放弃它。
因此,如果我启动一个 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)
Run Code Online (Sandbox Code Playgroud)
当我删除表时,这些“关系”锁不会被删除:
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)
Run Code Online (Sandbox Code Playgroud)
事实上,它又增加了两个锁……似乎如果我不断地创建/删除那个临时表,它每次都会增加 3 个锁。
所以我想一个答案是你需要足够的锁来处理在整个事务中添加/删除的所有这些表。或者,您可以尝试在查询之间重用临时表,只需截断它们以删除所有临时数据?
您是否创建了多个同名保存点而不释放它们?
我按照这些指示,重复执行
SAVEPOINT savepoint_name,但没有执行任何相应的RELEASE SAVEPOINT savepoint_name语句。PostgreSQL 只是屏蔽了旧的保存点,从不释放它们。它会跟踪每一个,直到耗尽锁的内存为止。我认为我的 postgresql 内存限制要低得多,只需要大约 10,000 个保存点就可以达到max_locks_per_transaction。
那么,您是否在单个事务中运行整个创建+查询?这也许可以解释这个问题。仅仅因为它发生在您删除表时并不一定意味着什么,这可能恰好是它耗尽可用锁的时间点。
使用视图可能是临时表的替代方案,如果您要创建这个东西然后立即删除它,我肯定会首先选择它。
| 归档时间: |
|
| 查看次数: |
15859 次 |
| 最近记录: |