MySQL Triggerのデメリットが大きいので使わないで欲しい
投稿日: 2018/06/08
MySQL
データベースのトリガーって、便利ですよね。
アプリケーションいらずでお手軽にプログラムが書けますし。
しかし、私は声を大にして言いたいです。
トリガーはデメリットが大きすぎて 「なるべくなら使わないで欲しい」と。
Trigger(トリガー)とは
トリガーはテーブルにINSERT・UPDATE・DELETEされたタイミングで、自動的に処理される機能のことです。
書き方など詳しくは別の記事を書いていますので、技術的な内容を知りたい方はそちらを参照してください。
トリガーの使い道
私が考えるトリガーの使い道は、次の通りです。
- ログ
- アプリケーションロジック
- データ移行
- 集計
ログ
何かイベントが発生したときに、履歴を保存したいときにトリガーは重宝します。
『MySQL TriggerのNEWとOLDを使いこなす』の記事でも、履歴を扱うサンプルを書きましたし、お手軽プログラムとしては作りやすいほうかと思います。
アプリケーションロジック
業務ロジック、ビジネスロジックなどと呼ばれる部分です。
私の拙い経験上、バッチ処理で多く使われているのを見かけますね。
例えば「マスタテーブルがデータ連携されたとき、トランザクションテーブルも更新する」とか。
「トランザクションテーブルが更新されたとき、ある条件において別のキューテーブルにためておく」とか。
システム要求仕様はさまざまなので、いろいろなパターンがあるのかと思います。
データ移行
システム再構築のときのような「せーの」で行う移行ではなく、他システム連携など レプリケーション機能を叶えるときにトリガーは使われます。
リアルタイムを実現するデータレプリケーションツールは、トリガーを多用しているイメージです。
集計
トランザクションテーブルのレコード数が多くなったとき、集計に時間がかかるようになりますよね。
その際、あらかじめ用意しておいた 集計用テーブルに計算した結果を書き込んでおくと、結果の表示が早くなります。
バッチで集計しても良いですが、リアルタイム性を担保するためにトリガーを使ったりしますね。
※性能要件が厳しいシステムはキューを使うかもしれませんが。
私がトリガーをおすすめしない理由
トリガー自体は「アプリケーションがなくてもデータベースだけでプログラムが組める」というそれだけ聞くととても良いもののように聞こえますね。
しかし、実は私 個人的にはトリガーは人におすすめしていません。
お仕事で色々な人やシステムと関わることがありますが、トリガーを駆使したシステムに良い思い出がないからです。
特に、 アプリケーションロジックをトリガーで書いてあるシステムは苦労しました。
私なりにトリガーのデメリットをまとめますので、良ければ参考にしてみてください。
- デメリットその1.複雑な仕様に耐えられない
- デメリットその2.拡張性に乏しい
- デメリットその3.ブラックボックス
- デメリットその4.データ移行しづらい
- デメリットその5.デバッグしづらい
デメリットその1.複雑な仕様に耐えられない
これはストアドプロシージャそのものに言えることかもしれません。
JavaやPHPのようなプログラミング言語を用いずとも、SQLでプログラミングはできます。
しかし、オブジェクト思考など高級言語のように上手な作りは相当ハードルが高いです。
DBだけでなんとかしたくなるのは、大体が複雑なテーブル構造を持つ業務システムなのかなと思ってますけど、そもそもそんな 複雑な業務情報を叶えるにはSQLだけでは不十分です。
一応叶えたはいいものの、 容易に変更できないカオスなプロシージャを私は何度も見てきました。
カオスな感じにならなく作れる人は天才かなと思ってしまうのです。
デメリットその2.拡張性に乏しい
デメリットその1と似ていますね。
改修しようとしたとき、データベース単体ができることを超えることが難しくなります。
トリガーを駆使したシステムだと、 データベース以外の技術で何とかするアプローチがしづらくなってしまうのです。
例えば、ある処理のパフォーマンスが遅いので改善しようとしたとき、トリガーだけの処理ですと改修にかなりの コストがかかります。
アプリケーションで対応可能な、キャッシュや並行処理はたやすくできません。
チューニング用のテーブル変更をするために、本番稼働を止めないといけないのもナンセンスです。
デメリットその1で挙げたようなオブジェクト指向やマイクロサービスのような拡張性には程遠いかと思います。
デメリットその3.ブラックボックス
システムの中を調査したことがある人は分かるかも?
トリガーがあると、 どこで何を処理しているか一気に分からなくなってしまいます。
例えば、ある項目にどんな値の入れ方をしているか調査するとき、その項目名でgrepなどしますよね。
開発者はまず、ソースコードをgrepしますが、そのとき高い確率で見つかりません。
SVNやGitなどのソース管理を知らない元請けのIT担当者が、しれっとトリガーを仕込んでいたりするともうお手上げです。
開発者からすると 「奇跡が起きるシステム」としか思えません(笑)
※偏見と私怨が含まれていますね。すみません。
トリガーのためにわざわざMySQLに接続して調査するのは、時間がかかってしまいますし、何よりデータとアプリが密結合してしまっている証拠のような気がします。
デメリットその4.データ移行しづらい
データ移行とは、読んで字のごとく「データ」の移行ですよね。
旧データベースから新データベースに移行するとき、 トリガーというプログラムロジックがあったとき、データ移行はシステム移行に変わってしまいます。
もしバージョンアップをしたいだけなのに、旧バージョンでしか動かないトリガーがあったとしたら?
MySQLからOracle、OracleからAmazon-RDSにデータ移行したいだけなのに、複雑なトリガーがあったとしたら?
そうすると、 データ構造を知るDBAだけなく、システム仕様を知っているアプリ開発者が必要になりますし、データ移行後のシステムテストだけでなく場合によっては単体テストも必要になってしまいます。
デメリットその5.デバッグしづらい
Javaを普段から扱っている人でしたら、当たり前のようにやっている 「ステップ実行」はできません。
※Oracleはできる?
私がデータベースに強い方々と関わったことがないからでしょうか。
「実行してみて動いたからOK」みたいな考えが基本なのかと感じています。
その考えは開発に向いていないのではと思います。
規模が大きくなったらどうする? 時間が経って忘れても改修できる? などお仕事をする上で欠かせない要素を叶えるためにも、簡単にデバッグできるものを扱わないといけないと私は考えます。
それでもトリガーを使うなら
私が考えるデメリットは、アプリケーションロジックをトリガーで書いた場合に起こりえます。
なおかつ、アプリケーションがあるにも関わらず、データベースでもプログラムを組むようなケースです。
ですので、もしトリガーを使いたいときが出てきたら 「トリガーだけで完結するもの」を目指して欲しいと思っています。
データ移行や レプリケーション機能でいかんなくメリットを発揮して欲しいですね。
まとめ
私が考える、トリガーのデメリットは 開発時ではなく運用時に起こるものばかりです。
アプリケーションとデータベースをしっかり分離させた設計や、現在より未来のことを考えたやり方を常に考えて開発したいものですね。