監査メカニズム(ログまたは変更履歴)は、データのすべての変更を追跡し、透明性を確保するために実装されます。主にいくつかのアプローチがあります:
監査トリガー(Audit Triggers): 特殊なAFTER/BEFORE INSERT/UPDATE/DELETEトリガーが、行の古い状態および/または新しい状態を別の監査テーブルに保存します。利点 — アプリケーションに対する透明性;欠点 — DML操作の可能な遅延。
履歴を別のテーブルに隔離(History Table): レコードのバージョニングが適用され、変更時に"古い"行が履歴テーブルにコピーされ、タイムスタンプが付けられます。基本テーブルには最新のデータのみが含まれます。
組み込みメカニズム(Change Data Capture, Temporal Tables): たとえば、SQL ServerではSYSTEM_VERSIONED TEMPORAL TABLEを有効にすると、DBMSが自動的に変更履歴を保持します。
CREATE TABLE user_audit ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT, action VARCHAR(10), old_value TEXT, new_value TEXT, changed_at DATETIME ); DELIMITER // CREATE TRIGGER audit_user_update AFTER UPDATE ON users FOR EACH ROW BEGIN INSERT INTO user_audit (user_id, action, old_value, new_value, changed_at) VALUES (OLD.id, 'UPDATE', OLD.name, NEW.name, NOW()); END// DELIMITER ;
質問: 変更履歴の完全なプロトコルが必要な場合、UPDATEだけのaudit-triggerで十分ですか?
回答: いいえ。完全な履歴を得るには、すべての操作タイプにトリガーを組み合わせる必要があります:INSERT(新しい行をログ記録)、UPDATE(変更をログ記録)、DELETE(削除されたレコードをログ記録)。
-- 各操作ごとに3つの別々のトリガーを作成する必要があります。さもなければ、履歴に"穴"ができます。
ストーリー1:会社は監査のためにUPDATEトリガーのみを使用しており、1年間削除されたレコードが記録されないことに気付かなかった。結果、インシデントを分析する際、重要なユーザーアカウントがいつ削除されたのかを特定できなかった。
ストーリー2:プロジェクトは変更の古い値と新しい値を1つのテキストフィールドにシリアル化されたJSONとして保持しており、分析が非常に困難になりました — 複雑なパーサーとレポート用の別のDBレプリカが必要になりました。
ストーリー3:高負荷のDBで、開発者はトリガーを通じて監査を実装し、ログテーブルのボリュームの増加を考慮しませんでした。時間が経つにつれて、履歴テーブルは基本テーブルの50倍になり、ストレージが過密になり、プロジェクト全体に障害を引き起こしました。