167

新しいデータベースを設計する必要があるたびに、変更の監査ログを保持するためにデータベーススキーマを設定する方法を考えるのにかなりの時間を費やします。

これについてはすでにいくつかの質問がありますが、すべてのシナリオに最適なアプローチが1つあることに同意しません。

また、各アプローチの長所と短所をリストしようとする、データベース変更のログの保守に関するこの興味深い記事に出くわしました。それは非常によく書かれていて、興味深い情報を持っていますが、それは私の決定をさらに難しくしました。

私の質問は次のとおりです。私が使用できる参照、おそらく本や、次のようないくつかの入力変数に基づいてどちらの方向に進むべきかを決定するために参照できる決定木のようなものはありますか。

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

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

1.作成および変更された日付とユーザーの列を追加します

表の例:

  • id
  • value_1
  • value_2
  • value_3
  • 作成日
  • Modified_date
  • によって作成された
  • 変更された

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

2.テーブルのみを挿入します

表の例

  • id
  • value_1
  • value_2
  • value_3
  • から
  • 削除済み(ブール値)
  • ユーザー

主な短所:外部キーを最新の状態に保つ方法は?巨大なスペースが必要

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

履歴テーブルの例:

  • id
  • value_1
  • value_2
  • value_3
  • value_4
  • ユーザー
  • 削除済み(ブール値)
  • タイムスタンプ

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

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

履歴テーブルの例:

  • table_name
  • 分野
  • ユーザー
  • new_value
  • 削除済み(ブール値)
  • タイムスタンプ

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

4

6 に答える 6

93

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

したがって、たとえば、販売取引を追跡するOpportunitiesというテーブルがある場合、実際には2つの別々のテーブルを作成します。

Opportunities
Opportunities_Content(またはそのようなもの)

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

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

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

おそらく、目次のPKをPageIDからの複数列のキーにし、リビジョンがIDタイプである場合はリビジョンにします。FKとしてRevision列を使用します。次に、次のようにJOINして統合レコードをプルします。

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

そこにいくつかのエラーがあるかもしれません...これは私の頭のてっぺんから外れています。ただし、別のパターンのアイデアが得られるはずです。

于 2010-01-07T12:55:30.560 に答える
14

SQL Server 2008を使用している場合は、おそらくデータキャプチャの変更を検討する必要があります。これは2008年の新機能であり、かなりの作業量を節約できます。

于 2010-01-06T18:47:01.013 に答える
7

参考文献はわかりませんが、誰かが何かを書いたと思います。

ただし、目的が単に何が起こったかを記録することである場合(監査ログの最も一般的な使用法)、単純にすべてを保持しないのはなぜですか。

timestamp
username
ip_address
procedureName (if called from a stored procedure)
database
table
field
accesstype (insert, delete, modify)
oldvalue
newvalue

おそらくこれはトリガーによって維持されます。

于 2010-01-06T18:34:13.670 に答える
5

ブログアプリケーション用の小さなサンプルデータベースを作成します。2つのテーブルが必要です。

blog:一意の投稿ID、タイトル、コンテンツ、および削除されたフラグを格納します。 audit:レコードID、ブログ投稿ID、変更タイプ(NEW、EDIT、またはDELETE)、およびその変更の日付/時刻を含む基本的な履歴変更のセットを格納します。次のSQLはblog、削除された列を作成してインデックスを作成します。

CREATE TABLE `blog` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
    `title` text,
    `content` text,
    `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    KEY `ix_deleted` (`deleted`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Blog posts';

次のSQLはauditテーブルを作成します。すべての列にインデックスが付けられ、blog.idを参照するaudit.blog_idに外部キーが定義されます。したがって、ブログエントリを物理的に削除すると、その完全な監査履歴も削除されます。

CREATE TABLE `audit` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
    `blog_id` mediumint(8) unsigned NOT NULL,
    `changetype` enum('NEW','EDIT','DELETE') NOT NULL,
    `changetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `ix_blog_id` (`blog_id`),
    KEY `ix_changetype` (`changetype`),
    KEY `ix_changetime` (`changetime`),
    CONSTRAINT `FK_audit_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `blog` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
于 2015-04-24T05:25:54.473 に答える
3

決定木のようなものはないと思います。いくつかの長所と短所(または要件)は実際には数えられないので。たとえば、成熟度をどのように測定しますか?

したがって、監査ログのビジネス要件を調整するだけです。これらの要件が将来どのように変化するかを予測し、技術要件を生成してみてください。今、あなたはそれを賛否両論と比較して、正しい/最良のオプションを選ぶことができます。

そして、安心してください、あなたがどのように決定するかは関係ありません、あなたが間違った決定をしたと思う誰かが常にいます。しかし、あなたは宿題をし、あなたはあなたの決定を正当化します。

于 2010-01-06T18:47:56.567 に答える
1

私は次の構造を使用しています:

id  int
user_id int
system_user_id  int
tenant_id   int
db_name varchar
model_name  varchar
model_primary_key   int
model_attributes    text
created_at  timestamp
ip  varchar
session_id  varchar
request_id  varchar
comments    text

これまでのところ、最大3億6,200万のレコード、マルチテナント、マルチデータベースでうまく機能します。

model_attributesは、キー値形式のjson文字列として、最も重要な変更点です。

于 2021-04-13T20:47:40.813 に答える