5

Python と psycopg2 を使用して一連のクエリを実行しています。cur.fetchmany(1000)約 200 万行の大きな一時テーブルを 1 つ作成し、それらの行を含むより広範なクエリを使用して実行することで、一度に 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 つのテーブルにしか触れていないため、どのように不足しているのかわかりません。テーブルロックが問題になる可能性があります...

4

3 に答える 3

7

テーブルを作成すると、トランザクションの最後まで続く排他ロックが取得されます。たとえあなたが先に進んでそれを落としたとしても。

したがって、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)

実際、さらに2つのロックが追加されました...その一時テーブルを継続的に作成/削除すると、毎回3つのロックが追加されるようです。

したがって、トランザクション全体でこれらすべてのテーブルが追加/削除されることに対処するには、十分なロックが必要になるというのが 1 つの答えだと思います。または、クエリ間で一時テーブルを再利用して、一時テーブルを切り捨ててすべての一時データを削除することもできますか?

于 2011-02-10T19:42:31.747 に答える
4

それらを解放せずに同じ名前で複数のセーブポイントを作成しましたか?

これらの指示に従い、繰り返し実行 SAVEPOINT savepoint_nameしましたが、対応するRELEASE SAVEPOINT savepoint_nameステートメントを実行することはありませんでした。PostgreSQL は古いセーブポイントをマスクしているだけで、解放することはありませんでした。ロック用のメモリがなくなるまで、それぞれを追跡しました。私のpostgresqlメモリ制限ははるかに低かったと思います. max_locks_per_transactionをヒットするのに約10,000セーブポイントしかかかりませんでした.

于 2012-09-07T04:46:46.260 に答える
1

では、作成 + クエリ全体を 1 つのトランザクション内で実行していますか? これはおそらく問題を説明するでしょう。テーブルを削除しているときに発生したからといって、必ずしも何も意味するわけではなく、たまたま空きロックがなくなった時点である可能性があります。

ビューを使用することは、一時テーブルの代わりになる可能性があり、このものを作成してすぐに削除する場合は、最初に選択することは間違いありません。

于 2010-06-28T13:07:45.573 に答える