web-dev-qa-db-ja.com

データベースへの変更を検出する方法(DDLおよびDML)

クライアントのSQLサーバーに多くのデータベースがあります。これらのデータベースは開発中であるため、開発者は設計、リファクタリング、データ変更などを行うことができます。めったに変更されないいくつかのデータベースがあります。私のクライアントは、それらすべてを安全に(バックアップして)保持し、環境の管理にある程度の時間を費やす必要があります。 (会社にはDB管理者の役職はありません。)長い議論の末、クライアントは復元が容易なため、毎日の完全バックアップ戦略を使用することにしました。

だからここに状況の要約があります:

  • データベースの数は毎日異なります。
  • 変更されたデータベース(データや構造が変更されたことを意味します)がバックアップされます。
  • 変更されなかったデータベースはバックアップされません。
  • ソリューションはデータベース構造に影響を与えません(要件は制限されません)
  • この「バックアップエンジン」は自動的に動作します。

主な問題:データベースが変更されたことを検出する方法。問題の最初の部分(DDLの変更)は、 DDLトリガー 。しかし、データの変更(DMLの変更)は問題です。すべてのデータベースのすべてのテーブルにDMLトリガーを適用して変更(パフォーマンス、拡張オブジェクトの管理など)を追跡することはできません。バックアップエンジンは、すべての変更を追跡して、各データベースをバックアップの準備ができているとしてマークする必要があります。

  • Change Data Capture は解決策ですが、重すぎるようです(SQL Server Enterprise Editionも必要です)。

  • 別の方法は、データベースファイルの変更(サイズまたは最終変更時間)を追跡することですが、正しく機能しません。データベースは、予約されているすべての空き領域と sp_spaceused を超えると、サイズを変更できます解決策ではありません。

  • トレースは解決策ですが、 パフォーマンスの問題 を引き起こし、追加の管理が必要です。

他のデータベース管理オブジェクト(統計など)に影響を与えずに実際のデータベース使用量を計算する解決策はありますか?テーブルのサイズを変更しないテーブルのデータの変更がトリガーされないことは確かです(私は思う)が、何もしないよりはましです。 SQL Server 2008の直接または間接的なソリューションを本当に探しています。

コメント、解決策、および考えをありがとう。

ADDED:

ここに解決策があります( Marian に感謝します):

Select
    NextLSN = MAX(fn.[Current LSN])
    ,Databasename = DB_NAME()
 from fn_dblog(NULL,    NULL) fn
     LEFT JOIN sys.allocation_units au
         ON fn.AllocUnitId = au.allocation_unit_id
     LEFT  JOIN sys.partitions p
         ON p.partition_id = au.container_id
     LEFT  JOIN sys.objects so
         ON so.object_id = p.object_id  
    WHERE 
    (
        (Operation IN 
       ('LOP_INSERT_ROWS','LOP_MODIFY_ROW',
            'LOP_DELETE_ROWS','LOP_BEGIN_XACT','LOP_COMMIT_XACT') 
            AND so.is_ms_shipped = 0)
        OR 
        ([Lock Information] like '%ACQUIRE_LOCK_SCH_M OBJECT%')
    )
13
garik

1つのアイデアは、毎日スナップショットを作成し、ファイルモニターを使用してディスク上のスナップショットファイルのサイズを監視することです。スナップショットは、データがそこに追加されたときにのみサイズが増加するため、実際のサイズ(報告されたサイズ)を監視するツールを見つけることができれば、有効です。

さて、私はこれを使用しなかったので、技術的な洞察を与えることはできません:-)。

別のアイデアは、各dbのトランザクションログ(もちろん、フルリカバリモードを使用している場合)を、ログから操作を読み取るフォーラム(db_fnlog ..または何か)で見た機能で確認することです。 、削除/挿入/更新があるかどうかを確認します。

これらは簡単なことではありません。しかし、それらが役立つことを願っています。

PS:ログ読み取り機能を備えた記事を見つけました(ちなみにfndblogです:-): Jens K. Suessmeyerによるトランザクションログを読み取ります

7
Marian
  • DDLの変更については、 デフォルトトレース を読むことができます。
  • DML変更の場合、CDCが少し重いことがわかっているため、関連するイベントのみをトレースする独自の軽量サーバー側トレースを実行できます。
1
Nomad

DMLの変更については、次のネイティブSQL Server監査機能を利用できます。

  • SQL Serverの変更の追跡
  • SQL Server変更データキャプチャ
  • SQL Server監査

それぞれに長所と短所がありますが、監査はMicrosoftによって導入された最新のものであるため、現在および将来のソリューションを組み込んで構築することをお勧めします。

監査機能のみが誰、いつ、どのように情報を提供することに注意してください

1
Ivan Stankovic

DDL変更の場合はDDLがトリガーしますが、DML変更の場合は3つの異なるオプションを使用して試すことができます

1)変更の追跡2)CDC(変更データキャプチャ)3)監査機能

変更の追跡については、以下のリンクを参照してください http://www.mssqltips.com/sqlservertip/1819/using-change-tracking-in-sql-server-2008/

この変更の追跡は、テーブルが変更されたかどうかに関係なく使用されますが、変更されたデータを見つけるのは非常に困難です。変更されたデータを見つけたい場合は、Chnage data Captureに移動できます。

SqlserverのAduitの場合、以下のリンクを確認できます http://blogs.msdn.com/b/manisblog/archive/2008/07/21/sql-server-2008-auditing.aspx

1
Anil Inampudi

トレースファイルを使用して、ddlの変更を検出できます。以下は、変更を取得するためのスクリプトです。

SELECT 
    te.name AS eventtype
    ,t.loginname
    ,t.spid
    ,t.starttime
    ,t.objectname
    ,t.databasename
    ,t.hostname
    ,t.ntusername
    ,t.ntdomainname
    ,t.clientprocessid
    ,t.applicationname  
FROM sys.fn_trace_gettable
(
    CONVERT
    (VARCHAR(150)
    ,(
        SELECT TOP 1 
            value
        FROM sys.fn_trace_getinfo(NULL)  
        WHERE property = 2
    )),DEFAULT
) T 
INNER JOIN sys.trace_events as te 
    ON t.eventclass = te.trace_event_id 
WHERE eventclass=164

次のスクリプトを使用して、テーブルとストアドプロシージャの変更を検出できます。

SELECT 
    SO.Name
    ,SS.name 
    ,SO.type_desc 
    ,SO.create_date
    ,SO.modify_date 
 FROM sys.objects AS SO
INNER JOIN sys.schemas AS SS 
    ON SS.schema_id = SO.schema_id 
WHERE DATEDIFF(D,modify_date, GETDATE()) < 50
AND TYPE IN ('P','U')
0
Anvesh