【问题标题】:postgresql: out of shared memory?postgresql:共享内存不足?
【发布时间】:2011-03-09 03:12:06
【问题描述】:

我正在使用 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.

有趣的是,这发生在我执行查询以删除更广泛的查询创建的一些临时表时。

为什么会发生这种情况?有什么办法可以避免吗?这很烦人,这发生在中途,这意味着我必须再次运行它。 max_locks_per_transaction 可能与什么有关?

注意:我没有做任何.commit()s,但我正在删除我创建的所有临时表,而且我只为每个“广泛”事务处理相同的 5 个表,所以我不看不到表锁用完可能是什么问题...

【问题讨论】:

    标签: python database postgresql psycopg2


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      当您创建一个表时,您会获得一个持续到事务结束的排他锁。就算你继续扔掉它。

      所以如果我启动一个 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 个锁。

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

      【讨论】:

        【解决方案3】:

        那么,您是在单个事务中运行整个 create + 查询吗?这也许可以解释这个问题。仅仅因为它发生在您删除表时并不一定意味着什么,这可能恰好是它用完空闲锁的时候。

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

        【讨论】:

        • 事务如何转化为游标和.commits?我没有做任何 .commits,但我使用新游标进行查询
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-13
        • 2013-05-05
        • 1970-01-01
        • 1970-01-01
        • 2012-09-18
        • 2019-07-27
        • 1970-01-01
        相关资源
        最近更新 更多