2017-03-22 26 views
0

とメモリ不足:何かがfooに挿入されたときにPostgresは、私は2つのテーブルを持っているトリガー

CREATE FUNCTION foo_before_insert() 
    RETURNS trigger AS 
    $BODY$ 
     BEGIN 

     INSERT INTO bar (id, xyz) 
     VALUES (
      NEW.id, 
      FooFunction(NEW.abc) 
     ); 

     RETURN NEW; 

     END; 
    $BODY$ 

    LANGUAGE plpgsql VOLATILE 
    COST 100; 

CREATE TRIGGER foo_before_insert 
    BEFORE INSERT ON foo 
    EXECUTE PROCEDURE foo_before_insert(); 

だから、何かがまたに挿入されています

CREATE TABLE foo (
    id serial primary key, 
    abc text 
); 

CREATE TABLE bar (
    id serial primary key, 
    xyz text 
); 

私はテーブルfooにトリガーを持っていますbarであり、abcカラムはFooFunctionによって操作されている。これは単純化されたバージョンです。

実世界FooFunctionは、経度と緯度のための2つの数値の引数を取り、単一のジオメトリ列を選択SELECTクエリにfor loopを行い、ジオメトリ列と入力して、いくつかのPostGISの機能を行い、およびブール値を返します。基本的に、この関数は、ポイントがポリゴンのセットから少なくとも1つのポリゴンの内部にあるかどうかを判断しようとしています。

は、ここでの機能の肉とジャガイモです:

FOR currentLinestring IN 
     SELECT linestring 
     FROM bla 
     WHERE yadda yadda... 
    LOOP 
     currentLinestring = ST_MakeLine(currentLinestring); 

     -- Can't make polygon with under 4 points 
     IF ST_NPoints(currentLinestring) < 4 THEN 
      EXIT; 
     END IF; 

     IF ST_Contains(ST_MakePolygon(currentLinestring), ST_SetSRID(ST_MakePoint(_lon, _lat), 4326)) = TRUE THEN 
      -- Is not out of bounds 
      RETURN FALSE; 
     END IF; 
    END LOOP; 

    -- Is out of bounds 
    RETURN TRUE; 

キャッチ関数は(質量更新などの)とき、トリガ外に100%正常に動作しますが、あるとき、トリガ関数内Postgresの登りのメモリ使用量メモリがすべて使い果たされ、Postgresがクラッシュするまで登ります。これは、私がCOPYで大規模なCSVを多分100kの行にしているときに起きています。

何が起こっているのですか?これをどうすれば解決できますか?

答えて

0

最初に重要なのは、トランザクションがコミットするとすぐにメモリが解放されることです(小さいCSVファイルで試してみてください)。そうでない場合は、問題がさらに悪化します。

検討する次のことは、多少のようになりますPostgreSQLサーバログにメモリダンプです:メモリコンテキストは、すべてそのメモリを持っている

TopMemoryContext: 221952 total in 17 blocks; 7440 free (41 chunks); 214512 used 
    TopTransactionContext: 8192 total in 1 blocks; 6384 free (0 chunks); 1808 used 
    CurTransactionContext: 0 total in 0 blocks; 0 free (0 chunks); 0 used 
    Type information cache: 24240 total in 2 blocks; 3744 free (0 chunks); 20496 used 
    RI compare cache: 24576 total in 2 blocks; 15984 free (5 chunks); 8592 used 
... 

を参照してください。

最新のPostgreSQLとPostGISがインストールされていることを確認してください。

いくつかのPostGIS関数でメモリがリークする可能性があります。 どちらが犯人であるかを知るまで、機能の一部を削除することによって、可能な限り絞り込んでください。

次に、問題を再現するための簡単なテストケースを作成し、すべての結果(メモリコンテキスト、&hellip;)を含め、PostGIS(またはPostGISなしで問題を再現できる場合はPostgreSQL)に問題を報告します。

この問題を回避するには、この問題を解決するにはこれが最善の方法です(例:作業を複数のトランザクションに分割します。

+0

個人的には、スタックの深さ制限を使い切る前に、メモリ制限にぶつかる再帰トリガだと思われます。 –

+0

@CraigRinger私はこれを可能性と考えていたが、そうは思わない。トリガー関数では、FooFunctionへの呼び出しを取り除き、挿入がうまくいった。 FooFunctionはSELECTを実行しているだけなので、どのように再帰的なトリガーを引き起こすかはわかりません。 – Tyler

+0

PostGISは時折メモリ豚として知られています。 –

関連する問題