web-dev-qa-db-ja.com

PostgreSQLなどのリレーショナルデータベースのトリガーは本当に必要ですか?

保存されたデータを検証してデータベースの整合性を保つためにトリガーを使用できることを知っています。しかし、データをデータベースに格納する前に、アプリケーション側でデータの検証を実行してはどうでしょうか。

たとえば、クライアントを保存し、DDLレベルでは簡単に実行できない検証を実行したいとします。 https://severalnines.com/blog/postgresql-triggers-and-stored-function-basics

別の例は監査です。

更新

トリガーとデータベーストランザクションがどのように連携するか。たとえば、挿入されるデータの検証を実行する場合などです。トランザクション内で行われます。以前に何が起こるか:トランザクションがコミットされるか、トリガーが実行されますか?

10
Yan Khonski

構築するアプリケーションシステムの種類によって異なります。

  • このアプリケーション専用の専用データベースを備えた1つのメインアプリケーションのみを含み、理想的にはアプリケーションとデータベースの進化を担当する1つのチームを含むアプリケーション中心のシステムを作成している場合、すべての検証ロジックを維持し、監査することもできます。アプリケーション内のロジック。

    これの主な利点は、アプリケーションとデータベースの間でビジネスロジックを分散する必要がないため、システムの保守と進化が容易になることが多いことです。おまけとして、特定のタイプのDBMSまたはDBMSベンダーにアプリケーションをあまり結び付けないでください。アプリケーションがトリガーを提供しない軽量のDBシステムを使用できるようにしたい場合、このアプローチは明らかに必要です。

  • ただし、多くの異なるアプリケーションが共通のデータベースを共有するシステムを作成し、将来どのアプリケーションがそのデータベースに書き込むか、または将来どのデータベースがデータをデータベースに書き込むためのアプリケーションを開発するかを事前に想定できない場合は、あなたのデータベースができる限り多くのデータの一貫性を保証する責任があるでしょう。そして、それはトリガーが本当に役立つところです。大規模なシステムでは、参照制約だけでは十分でないことがよくありますが、ストアドプロシージャを呼び出すトリガーで、必要なほぼすべての種類の検証を実装できます。

トリガーを使用するもう1つの理由はパフォーマンスです。複雑なデータモデルでは、クライアントアプリケーションで利用可能な現在のワーキングセットの一部ではない多くの追加データを使用する必要がある複雑な整合性ルールに遭遇することは珍しくありません。クライアント側で検証を可能にするために、最初にこれらのデータをすべてネットワーク経由で転送すると、パフォーマンスに大きな影響を与える可能性があります。

この古いSEの投稿も参照してください。 データベースクリーニング用のアプリケーションロジックとDBトリガー

そのため、構築しているシステムの種類を自分で決定し、トリガーがケースに適したツールであるかどうかを判断することができます。

12
Doc Brown

問題はデータの質に対する責任についてだと思います。

答えは、システムの見方によって異なります。

データベースをアプリケーションとは別の独立した独立した自律型サービスと見なす場合、データベースは、データベースに含まれるデータの一貫性と品質を保証する責任があります。基本的に、そのデータベースは別のアプリケーションで使用できるため、同じ一貫性と品質の動作を持つ2番目のアプリケーションに依存することはできません。このような状況では、APIと自律動作を公開するようにデータベースを設計する必要があります。このビューには、少なくとも2つのアプリケーションがあり、1つはデータベースであり、もう1つはそれを使用するアプリケーションです。

逆に、データベースは、アプリケーションの直接かつ完全な制御下にある複雑な形式のファイルと考えることができます。この意味で、データベースは純粋なシリアライゼーションおよびドキュメントナビゲーションツールとして機能します。 (JSONやXMLツールのように)クエリやドキュメントのメンテナンスをサポートするためにいくつかの高度な動作を提供する場合がありますが、(ほとんどのファイルストリームのように)必要はありません。この場合、ファイル内で正しい形式とコンテンツを維持するのは、プログラムの責任です。このビューには1つのアプリケーションがあります。

どちらのビューでも、次の質問は、データベースをファンシーファイルとして、または個別のサービスとしてサポートする方法です。これは次の方法で実現できます。

  • データベースプラットフォームがテーブル/ビュー/ストアドプロシージャ/トリガー/などの形式で提供するツールを使用する...
  • すべてのクライアントがデータベースにアクセスするために使用する必要があるサービス内にデータベース自体をラップする
  • データにアクセスするためにすべてのクライアントが使用する必要があるライブラリにデータベースをラップします。

それぞれに独自の長所/短所があり、システムが動作する環境のアーキテクチャ上の制約に依存します。

どちらのビューを使用するかに関係なく、境界でデータを検証することは常にコストがかかります。

  • ユーザーが入力するUIのフィールドを検証する
  • クライアントを離れる前にネットワーク/ APIリクエストを検証する
  • 何かを行う前に、サーバーでネットワーク/ APIリクエストを検証する
  • ビジネスルールに渡されるデータを検証する
  • 永続化する前にデータを検証する
  • 永続性から取得した後にデータを検証する
  • などなど

各境界でどの程度の検証が保証されるかは、検証を行わないことのリスクの程度によって異なります。

  • 2つの数値を掛け合わせる?
    • 間違った番号を取得することは問題ですか?
  • 指定されたメモリ位置でプロシージャを呼び出しますか?
    • そのメモリ位置には何がありますか?
    • オブジェクトが存在しない場合、または状態が悪い場合はどうなりますか?
  • 漢字を含む文字列に正規表現を使用していますか?
    • 正規表現モジュールはユニコードを処理できますか?
    • 正規表現はユニコードを処理できますか?
3
Kain0_0

いいえ、トリガーを使用して検証を行うことはできません。

データベースは、それ自体の整合性のみを担当します。検証に直面しているユーザーはすべて、アプリケーションで実行する必要があります。

データベースは、整合性のために3つのレベルの検証を実行します。 1つ目はフィールドレベルの検証です。フィールドが必要な場合があります。値がない場合(null)、エラーになります。チェック制約にすることもできます。ドメインには列挙された数の値があります。

次に、テーブル間に関係があります。 1つのテーブルに1つ以上の外部キーを格納し、このテーブルを他のテーブルに関連付け、値を「他のテーブル」の有効なキーにする必要があります。さまざまな国の住所をサポートする住所データベースを考えてみてください。住所の国キーは、既知の国を指す必要があります。データ(郵便番号など)が有効かどうかは、この整合性チェックの問題ではありません。

第三に、最も複雑なのはトリガーです。一般的なルールとして、これらは対処する必要があります(意図的ではありません)は、条件付きの整合性ルールに関係します。住所の例に戻ると、国に郵便番号がない場合、このリストにある国に郵便番号があると問題になります。したがって、チェックは次のようになります。この国に郵便番号がない場合、郵便番号フィールドはnullである必要があります。

検証はアプリケーションの問題です。ドイツの郵便番号が数字のみで構成されているという事実は、データベースではなく、アプリケーションが行うべきチェックです。行は細いので、トリガー(データベースの整合性を保護する)またはアプリケーション(ユーザーが検証に直面する)に何かが必要な場合は、場合によっては考えたり話し合ったりする必要があります。

2
Menno Hölscher

監査は、トリガーを効果的に使用する典型的な例です。トリガーによって実装された監査テーブルのおかげで、テスターに​​よるエラー(クライアントをあるサービスレベルから別のレベルに移動する)によっていくつかのエラーが見つかりました。監査にはトリガーを使用することを強くお勧めします。

検証couldフロントエンドレベルで行われますが、私が処理したデータベース(3000で生まれた人々など)で奇妙なエラーが発生しました。念のため、データベースに追加の検証レイヤーを設けることを強くお勧めします。もちろん、これらのタイプのエラーはチェック制約で回避でき、多くの場合、より効果的です(MS SQLでは、これらの方法が推奨されます。常にドキュメントを確認してください)。

1
Hila DG

リレーショナルデータベースのトリガーが本当に必要かどうかが問題なので、トリガーを使用する他のいくつかの使用例を次に示します。

  1. 他の回答に記載されている監査用。
  2. 広い意味での監査:データベースエントリが変更された場合、トリガーは非同期の後処理のためにイベントを記録できます。別のアプリケーションに毎晩エクスポートします。
  3. ビューのトリガー:トリガーを定義できますinstead of。これにより、ビューからエントリを挿入、更新、削除できます。トリガーは、これらのアクションを複数のテーブルに分散できます。これは、基になるテーブルの詳細を公開せずに、制限されたビューを使用可能にする方法です。
  4. データベースの方向転換を明示的に保存するには、テーブルAとBと中間テーブルRの間のN:M関係を想定します。Rのエントリを削除することを指定して、RからAおよびBへの外部キー制約を定義できます。 Bの対応するエントリが削除されます。ただし、ビジネスロジックでは、AのエントリがBのエントリと少なくとも1つの関係を持つ必要がある場合があります。この場合、Rの削除のトリガーは、このロジックの実施に役立ちます。Aのエントリの場合、Rの最後のエントリが削除されると、トリガーはAを削除できます。アプリケーション中心のビューでは、少なくとも2つの方向転換が必要です。これは検証の例です。他の例も考えられます:ユースケース(1)、(2)、および(3)のほかに、トリガーがターンアラウンドを保存する場合も、ユーザーがユーザーテーブルに挿入され、設定テーブルのデフォルトのセットが生成されます。
  5. 信頼:場合によっては、データベース管理者がアプリケーションを使用しないコマンドラインのエントリを変更します。管理者は注意深く作業し、何をしているのかを知っています。しかし、時々それらは間違っているかもしれません。一貫性が重要である場合、トリガーはその安全ベルトです。

欠点として、ビジネスロジックがレイヤー間に分散されており、これはメンテナンスにとって大きな欠点です。別の著者が書いたように、それはアプリケーションとデータベースの間の薄い境界であり、選択は必ずしも明確ではありません。私の個人的な見解では、トリガーは開発者に負担をかけます。開発にかかる時間を節約できます。明らかに、遅いネットワーク接続でのパフォーマンスを向上させるため、ユーザーの有効期限が向上します。

1
Claude