データベースのトリガーは悪ですか?[閉まっている]


186

データベースは悪い考えを引き起こしますか?

私の経験では、それらは意外な副作用を引き起こす可能性があり、デバッグが難しいため(特に、1つのトリガーが別のトリガーを起動した場合)、悪です。多くの場合、開発者はトリガーがあるかどうかを考えさえしません。

一方、常に新しいロジックが発生した場合、 FOOデータベースにが作成される場合は、FOOテーブルの挿入トリガーが最も確実な場所になります。

トリガーを使用するのは、の設定などの非常に単純な場合のみですModifiedDate


30
これは完全に正当な質問ですが、私はセンセーショナル派の称号はあまり好きではありません。「データベーストリガーを実装するときに考慮すべき最も重要な問題は何ですか?」はるかに良いでしょう。
Tamas Czinege 2009年

2
質問は答えを追加するために閉じていますが、「データベーストリガーはクロステーブル整合性制約に対して安全ですか?」も参照してください。(ネタバレ:いいえ、そうではありません)
Mifeet

16
このサイトは私を怒らせます。これは素晴らしい質問ですが、他の多くの質問と同様に、Q&Aのプリミティブバイナリ形式に適合しない質問を受け入れるための想像力が欠けているため、閉じられています。
2017

1
トリガー内のビジネスロジックには問題があります(悪意のある場合)。トリガー内のデータベースロジックに問題はありません(整合性、ロギング)。
グレッグガム

1
私はコードナビゲーションと何が起こっているのかを理解するためにIDEに依存するのが好きです。ロジックの半分がデータベースにあり、残りの半分が選択したプログラミング言語にある場合、私はそれを行うことができません。トリガーの代わりに、すべてのリクエストが通過するコントローラーを作成する方が簡単だと思います。代わりにすべての「トリガー」を適用できます。
ムハンマドウメル

回答:


147

トリガーの主な問題は

  • それらは完全にグローバルです-テーブルアクティビティのコンテキストに関係なく適用されます。
  • 彼らは内密です。それらが意図しない(そして非常に神秘的な)結果であなたを傷つけるまで、彼らがそこにいることを忘れるのは簡単です。

これは、適切な状況で慎重に使用する必要があることを意味します。私の経験では、これはリレーショナルインテグリティの問題に限定されます(宣言的に取得できるよりも細かい場合もあります)。通常、ビジネスまたはトランザクションの目的ではありません。YMMV。


20
これらは、場合によっては2つの利点です。
Johnno Nolan

18
「ステルス」は素晴らしい言葉です。だからこそ、私は彼らから遠ざかる傾向があります。あまりにも頻繁に、彼らは忘れられたり無視されたりします。私の個人的な経験では、トリガーを再検討すると、しばしば自分の額が軽くなります。
クリスチャンヌンチャアート2009年

5
データの整合性や監査などに必要な理由は、グローバルなためです。それはマイナスではなく、プラスです。
HLGEM 2010年

4
@RobertŠevčík-Robajz、あなたはあなたが知っているすべての開発者が無能だと言っていますか?
HLGEM 2012年

3
@HGLEM、トリガーを解決するスペシャリストがいるはずだと同意します。実際のシナリオ-ありません。実際のシナリオ-忘れられたトリガーに関連するバグを特定するために費やされた日数。実際のシナリオ-トリガーロジックはアプリケーションロジックに必死に押し出されており、簡単にリファクタリングして単体テストを実行できます。「引き金に近づかない」と言われるのは、私が実際に取り組んでいることです...窓が壊れるのは石のせいではなく、引き金のせいではありません。
Rbjz

80

いいえ、それらは実際には良いアイデアです。特定のトリガーに問題がある場合は、正しく実行していませんが、通常はトリガー自体の概念ではなく、実装に問題があることを意味します:-)。

トリガーは、DBMS固有のアクティビティを、それが属するデータベースの制御下に置くため、よく使用されます。DBMSのユーザーは、そのようなことを心配する必要はありません。データの整合性はデータベース自体にあり、それを使用するアプリケーションやユーザーにはありません。データベースに制約やトリガー、その他の機能がなければ、ルールを適用するのはアプリケーションに任され、1人の不正なまたはバグのあるアプリケーション/ユーザーがデータを破壊するだけです。

たとえば、トリガーがなければ、自動生成された列などの不思議なことは存在せず、列を選択するときに各行の関数を処理する必要があります。これは、DBMSのパフォーマンスを低下させる可能性が高く、挿入/更新時に自動生成された列を作成する方がはるかに優れています。

また、トリガーがないと、事前トリガーなどのデータルールがDBMSで適用されず、列が特定の形式になるようになります。これは、一般に単なる外部キーのルックアップであるデータ整合性ルールとは異なることに注意してください。


9
「それらを選択するときに、各行の関数を処理します」。この目的には、トリガーよりも関数ベースのインデックスを使用することをお勧めします。
tuinstoel 2009年

10
必ずしもそうとは限りませんが、トリガーはおそらく、行が挿入または更新されたときにのみ実行されます。関数ベースのインデックスは、すべての選択に対して実行されます。使用パターンに応じて、一方がおそらくもう一方よりも優れています。しかし、どちらも常に他よりも優れています。
jmucchiello 2010

@tuinstoel:私はあなたの声明に同意しなければならないいくつかの時間を。たとえば、Oracleは、関数が決定論的であることを証明できる場合にのみ、関数ベースのインデックスを作成します。場合によっては、それを証明できないことがあります(たとえば、テーブルのデータが変更されないことがわかっている場合でも、関数がテーブルからのルックアップを含む場合)。
Adam Paynter 2010年

50

ツールは決して悪ではありません。これらのツールのアプリケーションは悪である可能性があります。


11
コメントを読んだ後、これ以上衝突することはありません。一方では、私は2番目の修正であり、銃は本質的に邪悪ではないと信じています。それは銃を使用する人です。一方で、それがARE evilの引き金になると思います...私は実存的なメルトダウンを抱えていると思います...
vbullinger

37
@vbullinger銃は悪ではありませんが、そのトリガーは;)
Darragh Enright

2
:D一般化は危険です(再帰的に)。異端審問官が告白を「誘発」するために使用する拷問「道具」に来ましたか?とにかく視点の+1。
Rbjz

22

同意する。トリガーに関する問題は、トリガーではなく人です。調べること、検討すること、および物事を正しくチェックするコーダーの負担を増やすことはより多くなりますが、私たちの生活をよりシンプルにするためにインデックスを破棄することはありません。(悪いインデックスは悪いトリガーと同じくらい悪いものになる可能性があります)

(私の心の中で)トリガーの重要性は次のとおりです...-
すべてのシステムは常に
有効な状態にある必要があります-この有効な状態を強制するコードは一元化する必要があります(すべてのSPに記述されているわけではありません)

メンテナンスの観点から見ると、トリガーは有能なコーダーやジュニア/アマチュアの問題にとって非常に役立ちます。しかし、これらの人々は何らかの方法で学び、成長する必要があります。

それはあなたの作業環境にかかっていると思います。よく学んで信頼できる人がいるのですか?そうでない場合は、2つの選択肢があるように見えます。-
補正するために機能を失う必要があることを受け入れます。
必要があることを受け入れる-別の人またはより優れたトレーニングと管理が必要であることを受け入れる

彼らは厳しいように聞こえます、そして私は彼らがそうであると思います。しかし、それは私の心の中で、基本的な真実です...


3
>>>トリガーの問題は人です。ええ、もし人々がアセンブリでコードを書いたり、くだらないGUIで作業したりできれば、デザインの悪いドアを押したり引いたりするかどうかを正しく推測できます...人々が繰り返し間違ってしまう「機能」は「悪」です。
Fakrudeen、2011

1
@Fakrudeen、トリガーを間違って取得した開発者は、データベースにアクセスできません。
HLGEM 2014

20

トリガーは悪であるだけでなく、優れたデータベース設計に必要だと思います。アプリケーションプログラマーは、データベースはアプリケーションによってのみ影響を受けると考えています。彼らはしばしば間違っています。データの変更がどこから来たかに関係なくデータの整合性を維持する場合、トリガーは必須条件であり、一部のプログラマーは、独自のアプリケーション以外のものが何かに影響を及ぼしているとは考えられないため、それを回避するのは愚かです。有能なデータベース開発者であれば、トリガーを設計、テスト、またはトラブルシューティングすることは難しくありません。また、(私と同じように)トリガーを見てトリガーが予期しない結果を引き起こしていると判断することも難しくありません。spで参照していないテーブルにFKエラーがあるというエラーが発生した場合は、トリガーが問題を引き起こしていること、そして有能なデータベース開発者もそうであることを、私はそれについても考えずに知っています。アプリケーションにのみビジネスルールを配置することは、ルールが存在し、プロセスに違反していることを他の人が知らないため、私が不良データを発見した最大の原因です。データ中心のルールはデータベースに属し、トリガーはより複雑なルールを適用するための鍵となります。


データ中心のルールはデータベースに属しています
アブサン

私がいたsome programmers are too ethnocentric to consider that something other than their prized application may be affecting things
Kid101

13

主に、はい。

トリガーの難しさは、「背後で」何かを行うことです。アプリケーションを保守している開発者は、それがそこにあることを簡単に認識できず、気付くことなく、物事を台無しにする変更を加えることができました。

メンテナンス作業を追加するだけの複雑なレイヤーを作成します。

トリガーを使用するのではなく、ストアドプロシージャ/ルーチンは通常、同じことを行うように作成できますが、明確かつ保守可能な方法で行います。


12
これは欠点ではなくトリガーの利点です!ストアドプロシージャは、データが変更されるたびに呼び出されるとは限りません。ここでは、GUI以外にもデータを変更できる多くの方法があります。
HLGEM 2009年

2
HLGEM、それはあなたのアクセス制御に依存します。ストアドプロシージャを使用しない限り、テーブルへの変更を直接拒否できます。
Rbjz、2011年

1
重要なのは、たとえば、2つのテーブルのレコードを常に作成して破棄する必要がある場合、どのようにデータベースにアクセスしても、自分が誰であるか、どのような権限を持っているかに関係なく、トリガーが唯一の正当なソリューションであるということです。 。割り当てられている権限が多すぎたり、正しくない場合があり、どのストアドプロシージャが使用されるかを人々に知らせることができるという単なる事実は、データベースの整合性が失われるリスクがあることを意味します。これは、外部キーの関係とまったく同じです。これは、データベースエンジンによって実行される、最良かつ最も信頼性の高いものです。
Triynko 2013年

2
レコードを常に一緒に作成/破棄する必要がある場合は、それらが確実に作成されるようにするチェック制約を作成します。こうすることで、ルールを破った人が、知識や同意なしに魔法のように正しいことをするという隠された振る舞いではなく、エラーを受け取ります。
MarkR 2013年

9

トリガーは非常に強力で便利です。トリガーが問題の最良の解決策となるシナリオはいくつもあります。

また、非常に優れた「ハッキング」ツールでもあります。コードとデータベースの両方をすぐに制御できない状況がよくあります。コードの次のメジャーリリースまで2か月待たなければならない場合でも、データベースにパッチをすぐに適用できます。その後、テーブルにトリガーを配置して、いくつかの追加機能を実行できます。その後、コードのリリースが可能な場合は、必要に応じてこのトリガーを同じ機能のコード化されたバージョンに置き換えることができます。

結局のところ、何をしているのか分からなければ、すべてが「悪」です。トリガーを理解できない開発者がいるためだと判断することは、一部の人が運転できないために車が悪いと主張することと同じです...


7

トリガーには用途があります。ロギング/監査と「最終変更」日付の維持は、以前の返信で言及されている2つの非常に優れた用途です。

ただし、優れた設計の中心的な信条の1つは、ビジネスルール/ビジネスロジック/呼び出すものはすべて1か所に集中する必要があるということです。ロジックの一部を(トリガーまたはストアドプロシージャを介して)データベースに配置し、一部をアプリケーションに配置すると、その原則に違反します。両方の場所でロジックを複製すると、常に互いに同期しなくなるため、状況はさらに悪化します。

すでに言及されている「最小の驚きの原則」問題もあります。


3
そうですね、データベースの1か所に配置する必要があります。データの整合性に影響を与えるロジックは、常にデータベース内に存在する必要があり、データベース内のデータに影響を与えるときに呼び出される場合と呼び出されない場合があるアプリケーションには決して存在しないでください。
HLGEM 2010年

1
@HLGEM:これは、データベースがデータが有効かどうかを判断できる情報にアクセスできるかどうかによって異なります。常にそうであるとは限りません。バリデーターが別の組織(たとえば、クレジットカードまたは銀行口座の詳細)にある場合、DBはそれが正しいかどうかを知ることができません—これが銀行のDBではないと想定してください!—そして、それは執行のためのアプリケーションに依存する必要があります。サーバーの展開に関しては悪いので、データベースにサードパーティのサービスへのランダムな接続を確立させることは望ましくありません。
ドナルフェロー2010年

@HLGEM:すべてのアプリケーションロジックをデータベースに配置するオプションを完全に排除する準備はできていませんが、他の場所に配置する方が効果的であることがわかります。データベース。アプリがオブジェクトレイヤーを介してのみデータベースにアクセスする限り、常に呼び出されるロジックと同じ保証が適用されます。
Dave Sherohman、

2
オブジェクトレイヤーを介してデータベースにデータを挿入するだけのビジネスアプリケーションに取り組んだことは一度もありませんでした。一度に1つのレコードのみを処理するように設計されたプロセスを通じて、100万件のレコードのインポートまたはすべての価格の更新を行うのは愚かです。オブジェクトレイヤーは、データの整合性を適用するための正確な場所ではありません。そのため、多くのデータベースには整合性の問題があります。
HLGEM 2010年

@HLGEMそのため、トランザクション内のすべてのチェンジセットを使用してトリガーのように機能するように、ORMの拡張に取り組んでいます。少しばかげているように見えますが、アプリケーションにビジネスロジックをすべて含めることができます。ただし、そうでない場合もあります(一括更新が必要なテーブルはごくわずかです)。また、すべての開発者が最も使いやすい言語で作成し、使用したすべてのオブジェクト抽象化にアクセスできる場所でそれらを使用できるようになります。
アダマン

6

トリガーは、適切に使用すると優れたツールになります。特に、変更の監査、要約テーブルへの入力などに適しています。

これで、他のトリガーを開始する1つのトリガーで「トリガー地獄」になる場合、それらは「悪」になる可能性があります。私はかつて、「フレックストリガー」と呼ばれるCOTS製品を扱っていました。動的SQL文字列が実行されるたびにコンパイルされるため、これらのトリガーはテーブルに格納されました。コンパイルされたトリガーは、ルックアップを実行し、そのテーブルに実行するflexトリガーがあるかどうかを確認してから、「flex」トリガーをコンパイルして実行します。理論的には、製品は簡単にカスタマイズできるので、これは本当にクールなアイデアのように聞こえましたが、実際には、実行する必要があるすべてのコンパイルのためにデータベースがかなり爆発していました...

ええ、そうです、あなたが自分のやっていることを見通したままにしておけば素晴らしいです。監査、要約、自動シーケンスなどの非常に単純なものである場合、問題はありません。テーブルの成長率と、トリガーがパフォーマンスに与える影響を覚えておいてください。


6

高レベルでは、トリガーには2つのユースケースがあります1

1)何かを「自動的に」起こすため。この場合、トリガーは副作用を引き起こし、実行された(プリミティブ)演算子の挿入、更新、または削除を想定して予期しない方法でデータを変更し、トリガーを起動させました。

ここでの一般的な合意は、トリガーは実際に有害であるということです。これらは、INSERT、UPDATE、またはDELETEステートメントのよく知られたセマンティクスを変更するためです。これら3つのプリミティブSQL演算子のセマンティクスを変更すると、SQLプリミティブを使用して操作したときに、予期したとおりに動作しないデータベーステーブルで後で作業する必要がある他の開発者を悩ませるでしょう。

2)データ整合性ルールを実施するために、宣言的に処理できるルール(CHECK、PRIMARY KEY、UNIQUE KEY、およびFOREIGN KEYを使用)以外のルール。この使用例では、トリガーが行うすべてのトリガーはQUERY(SELECT)データであり、INSERT / UPDATE / DELETEによって行われている変更が許可されているかどうかを確認します。宣言的制約が私たちにしてくれるように。この場合にのみ、私たち(開発者)が施行をプログラムしました。

後者のユースケースでトリガーを使用しても害はありません。

私はそれについてブログを書いています:http//harmfultriggers.blogspot.com


参照整合性のためにトリガーを使用する場合、同時実行性の問題を処理するよりも困難です。
WW。

2
同意した。しかし、他の手段を使用する方が簡単ですか?
Toon Koppelaars、2011

私は、能力のない開発者がいる場合にのみ、1つ目が有害であることを主張します。
HLGEM 2015年

笑いながらも無能な開発者がたくさんいます。
ハッシュテーブル2017

5

トリガーは、必要な機能を実現するための最も直接的な方法であるトリガーを常に使用する必要があると思う開発者と、絶対に使用しない開発者を知っています。それは2つの収容所の間の教義のようです。

ただし、私はMarkRに個人的に完全に同意します。(ほぼ)トリガーと機能的に同等のコードを常に記述できるため、より目立ち、保守が容易になります。


データベースをヒットするためのすべての作業がアプリケーションコードを通過するわけではありません。
HLGEM 2015年

5

悪じゃない。彼らは実際にのようなものを簡素化します

1.レコードまたはデータベーススキーマへの変更のログ記録/監査

本番環境での変更をロールバックするトリガーをALTER TABLEに設定できます。これにより、偶発的なテーブルの変更が防止されます。


2.複数のデータベースにわたる参照整合性(主/外部キー関係など)の実施


DDLステートメントをロールバックできますか?
Andrew Swan

通常はありません。これを止める唯一の方法は、ユーザーのログインからその権限を削除することです。
jmucchiello 2010

一部のデータベースエンジンでは可能です(例:PostgreSQL)。
ニコラス

@Andrew-SQL Serverではできます。SQL Server 2005+には、などのイベントで発生するDDLトリガーもありますALTER TABLE
マーティン・スミス

4

いや、彼らは邪悪ではありません-彼らは単に誤解されています:-D

トリガーは有効に使用できますが、最終的に事態を悪化させるレトロハックとしてはあまりにも頻繁に使用されます。

アプリケーションの一部としてDBを開発している場合、ロジックは常にコードまたはsprocsで呼び出しを行う必要があります。トリガーは、後でデバッグの痛みにつながるだけです。

ロック、デッドロック、およびDBがディスク上のファイルにアクセスする方法を理解している場合、トリガーを適切に使用する(たとえば、直接DBアクセスの監査またはアーカイブ)ことは非常に価値があります。


4

彼らは悪だと言うのは大げさですが、メッシュの原因となる可能性があります。1つのトリガーの起動によって他のトリガーが起動されると、それは本当に複雑になります。問題があるとしましょう:http : //www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html

トリガーを使用してOracleでビジネスロジックを実行することは、複数の同時実行の問題があるため、見かけよりも困難です。他のセッションがコミットするまで、他のセッションの変更は表示されません。


4

彼らは間違いなく悪ではありません。列の名前を変更したり、列を2つの列に分割したり、その逆(例:名前/姓の場合)を行ったり、移行を支援したりするときに、データベーススキーマのリファクタリング中に貴重なトリガーを見つけました。

また、監査にも非常に役立ちます。


4

この回答は、特にSQL Serverに適用されます。(それは私が知らない他のRDBMSにも当てはまるかもしれませんが、答えとしてそれを与えることを望んだでしょうここではこれのまとまりとして閉じられました。)

これまでの回答のいずれにも言及されていない1つの側面は、セキュリティです。デフォルトでは、トリガーは、トリガーを起動させるステートメントを実行するユーザーのコンテキストで実行されるため、すべてのトリガーを確認しない限り、セキュリティ上の脅威が発生する可能性があります。

トリガーのセキュリティの管理」という見出しの下のBOLに示されている例GRANT CONTROL SERVER TO JohnDoe ;は、自分の権限をエスカレートするためにコードを含むトリガーを作成するユーザーのものです。


3

副作用がある場合、それは設計上の問題です。一部のデータベースシステムでは、自動インクリメントフィールド(主キーIDフィールドなど)を設定する他の可能性はありません。


3

私はそれらは悪である可能性があると思いますが、開発中の他のものと同じくらい悪です。

私は実際にはあまり経験がありませんが、私が取り組んだ最近のプロジェクトで彼らを経験したので、この結論に至りました。彼らが抱えている問題は、ビジネスロジックがコードライブラリデータベースのです。

私はそれをsprocsを使用する場合の同様の議論と見なします。多くの場合、SQLでビジネスロジックをデータベースに書き込むのが本当に上手な開発者がいる一方で、ビジネスロジックが他の場所にはない開発者がいます。

したがって、私の経験則は、プロジェクトの構造を調べることです。ビジネスロジックをデータベースに格納することが現実的であると思われる場合は、トリガーがあると便利です。


1

実際、非常に頻繁にトリガーが悪用されています。実際、ほとんどの場合、それらを必要とすることすらありません。だからといって必ずしも悪いことではありません。

トリガーが役立つシナリオは、ソースコードがないレガシーアプリケーションがあり、それを変更する方法がない場合です。


1

トリガーのアイデアは悪ではなく、トリガーのネストを制限することは悪です。

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