監査ログのデータベース設計 [closed] 質問する

監査ログのデータベース設計 [closed] 質問する

新しいデータベースを設計する必要があるたびに、変更の監査ログを保持するためにデータベース スキーマをどのように設定すればよいかについてかなりの時間をかけて考えます。

これについてはすでにここでいくつか質問されていますが、すべてのシナリオに対して単一の最善のアプローチがあるという考えには同意しません。

私もこれに遭遇しましたデータベースの変更ログの維持に関する興味深い記事それぞれのアプローチの長所と短所を列挙しようとしています。非常によく書かれていて、興味深い情報も含まれていますが、私の決断をさらに難しくしています。

私の質問は次のとおりです:次のような入力変数に基づいて、どの方向に進むべきかを決定するために参照できる参考資料、たとえば本や意思決定ツリーのようなものはありますか?

  • データベーススキーマの成熟度
  • ログの照会方法
  • 記録を再作成する必要がある可能性
  • より重要なのは書き込みパフォーマンスか読み取りパフォーマンスか
  • 記録される値の性質(文字列、数値、BLOB)
  • 利用可能なストレージスペース

私が知っているアプローチは次のとおりです。

1. 作成日と変更日、およびユーザーの列を追加する

表の例:

  • id
  • 値_1
  • 値_2
  • 値_3
  • 作成日
  • 更新日
  • によって作成された
  • によって変更

主な欠点: 変更履歴が失われます。コミット後にロールバックできません。

2. 表のみを挿入する

表の例:

  • id
  • 値_1
  • 値_2
  • 値_3
  • から
  • 削除済み (ブール値)
  • ユーザー

主な欠点: 外部キーを最新の状態に保つにはどうすればいいでしょうか? 膨大なスペースが必要

3. テーブルごとに個別の履歴テーブルを作成する

履歴テーブルの例:

  • id
  • 値_1
  • 値_2
  • 値_3
  • 値_4
  • ユーザー
  • 削除済み (ブール値)
  • タイムスタンプ

主な欠点: 監査対象のテーブルをすべて複製する必要があります。スキーマが変更された場合は、すべてのログも移行する必要があります。

4. すべてのテーブルを統合した履歴テーブルを作成する

履歴テーブルの例:

  • テーブル名
  • 分野
  • ユーザー
  • 新しい値
  • 削除済み (ブール値)
  • タイムスタンプ

主な欠点: 必要に応じてレコードを簡単に再作成 (ロールバック) できますか? new_value 列は、すべての異なる列タイプをサポートできるように、巨大な文字列である必要があります。

ベストアンサー1

いくつかの wiki プラットフォームで使用されている方法の 1 つは、識別データと監査対象のコンテンツを分離することです。これにより複雑さが増しますが、古いレコードがどのようなものであったかをユーザーに知らせるために編集されたフィールドのリストをマッシュアップする必要がなくなるため、完全なレコードの監査証跡が得られます。

例えば、次のようなテーブルがあったとします機会販売取引を追跡するには、実際には 2 つの別々のテーブルを作成します。

機会
機会_コンテンツ(またはそのようなもの)

機会テーブルには、レコードを一意に識別するための情報と、外部キー関係を参照するための主キーが格納されます。機会_コンテンツテーブルには、ユーザーが変更でき、監査証跡を残したいすべてのフィールドが含まれます。コンテンツテーブルには独自のPKと、変更者と変更日のデータが含まれます。機会テーブルには、現在のバージョンへの参照と、メイン レコードが最初に作成された時期と作成者に関する情報が含まれます。

簡単な例を次に示します。

CREATE TABLE dbo.Page(  
    ID int PRIMARY KEY,  
    Name nvarchar(200) NOT NULL,  
    CreatedByName nvarchar(100) NOT NULL, 
    CurrentRevision int NOT NULL, 
    CreatedDateTime datetime NOT NULL

内容は次の通りです。

CREATE TABLE dbo.PageContent(
    PageID int NOT NULL,
    Revision int NOT NULL,
    Title nvarchar(200) NOT NULL,
    User nvarchar(100) NOT NULL,
    LastModified datetime NOT NULL,
    Comment nvarchar(300) NULL,
    Content nvarchar(max) NOT NULL,
    Description nvarchar(200) NULL

Revision が ID タイプである場合、コンテンツ テーブルの PK を PageID と Revision からの複数列キーにすると思います。Revision 列を FK として使用します。次に、次のように JOIN して統合レコードを取得します。

SELECT * FROM Page
JOIN PageContent ON CurrentRevision = Revision AND ID = PageID

いくつか間違いがあるかもしれません...これは私の頭に浮かんだものです。ただし、別のパターンのアイデアは得られるはずです。

おすすめ記事