pg_trigger_depth()は、トリガーのカスケード(再帰)を防止するために使用するのは悪いですか?


8

pg_trigger_depth() = 0トリガーのカスケード(再帰)を防止するときに(デバッグ以外の目的で)使用するのが悪いのはなぜですか?

誰かがなぜそれが悪いのかを示すコードを提供できますか?

複数のトリガーが同じデータで同時に機能している場合、トリガーを使用して停止する条件pg_trigger_depth() = 0は、2番目に機能するトリガーを停止するためだと思います。

私はそれがこの(私の)質問に対する良い解決策になると思いましたが、そうでないと言われました:

それは良い質問をするだろうと思った。

これはソリューションとしてここに提供されています:

Postgres 9.3ドキュメント:

https://www.postgresql.org/docs/9.3/static/functions-info.html

回答:


1

はい、行動を依存させることは常に悪いことです pg_trigger_depth()

たぶん私は毛布の発言を少し嫌っていますが、それで何ができるでしょうか なぜそのような機能が必要なのについて、私が理解できる議論はありません。データベースの主な目的は、データの整合性を確保することです。そして、私の知る限り、私は間違っている可能性があり、そのような使用は常に ある潜在的なデータ整合性の違反。@アーウィンの答えで彼は「もしあなたが忘れたら」と言います。整合性を確保するポイントは、その可能性を排除することです。エージェントがすべてを覚えていて、結果とその周りのコードを理解できれば、からでもデータの整合性を得ることができます。

いくつかの用語を紹介しましょう。プログラミングでは、

  • プログラマがアクセスできるすべてのものを含む「状態」
  • 実行環境を含む「実行コンテキスト」

さらに、関数の用語があり、純粋な関数と呼ぶ状態はありません 。

関数は常に、同じ引数値が与えられた場合、同じ結果値を評価します。関数の結果の値は、プログラムの実行中またはプログラムの異なる実行間で変化する可能性のある非表示の情報や状態に依存したり、I / Oデバイスからの外部入力に依存したりすることはできません(通常、以下を参照)。

純度のための区別は、それは、コンピュータ、またはプログラマの代わりに何かを覚えて任意の負担がなくなるために有用である:f(x) = yある常に真。ここで、最悪の場所であるデータベースに純粋性を違反しています。そして、あなたはそれを複雑でエラーが発生しやすい方法で行っています-DBアプリケーションの状態で内部実行コンテキストを明白なものにします。

それは欲しくない。精神的に緩衝しなければならない複雑さを考慮してください。

  • Table ATrigger A火災
    • Trigger AいつものDMLを発行Table B発射、Trigger B
      • Trigger B条件付きにDMLを発行Table A発射、Trigger A
      • Trigger BいつものDMLを発行Table A発射、Trigger A
    • Trigger A条件付きにDMLを発行Table B発射、Trigger B
      • Trigger B条件付きにDMLを発行Table A発射、Trigger A
      • Trigger BいつものDMLを発行Table A発射、Trigger A

それが複雑に見える場合は、「条件付きで」「発生したが、常に発生するとは限らない」「発生しなかったが、他の場所で発生する可能性がある」とさらに拡張できることに注意してください。

pg_trigger_depth()役立つためにも、同様に複雑な一連のイベントが必要です。そして今、あなたは実行がそのチェーンの実行内容に依存することを望みますか?

私はこれを避けます。トリガーシステムがこのように複雑な場合、手榴弾を使ってクローゼットの中でホットポテトを一人で遊んでいるため、うまく終了しないようです。


10

それ自体を使用することは悪くありません(IMHO)。あなただけの影響を意識する必要があります。

原則pg_trigger_depth() < 1としてpg_trigger_depth() = 0、の代わりに作成しますが、ここでは重要ではありません。次のようなトリガーについて話しています。

CREATE TRIGGER my_trigger
AFTER INSERT ON my_tbl
FOR EACH ROW
WHEN (pg_trigger_depth() < 1)
EXECUTE PROCEDURE my_trigger_func();

後でトリガーを追加するトリガーを追加した場合、代わりに何も起こりません。トリガーは非トリガーイベントにのみ反応します。設定によっては、これがまさにあなたが望むものかもしれません-またはこれを忘れて、後でこのトリガーを(また)トリガーするトリガーをさらに追加する場合は、一種のトラップです。デフォルトの動作を変更しています。これを明確に文書化してください。

は、同じトリガーだけでなく、任意のトリガーpg_trigger_depth()カウントして再帰を防止します。そのため、他のトリガーから呼び出された場合も、条件がトリガーの起動を防ぎます。マニュアル:

PostgreSQLトリガーの現在のネストレベル(直接または間接的にトリガー内から呼び出されない場合は0)

関連:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.