質問

私の上司は昨日、顧客からの質問があり、SQL Serverデータベースで誰がいくつかのデータを削除したかを知る方法を尋ねました(それが重要な場合はExpress Editionです)。

これはトランザクションログから見つかると思いました(切り捨てられていないことを提供してください) - これは正しいですか?もしそうなら、あなたは実際にこの情報を見つけることをどうやって見つけますか?

役に立ちましたか?

解決

ExpressでFN_DBLOGを試したことはありませんが、利用可能な場合は次のとおりに削除操作が得られます。

SELECT 
    * 
FROM 
    fn_dblog(NULL, NULL) 
WHERE 
    Operation = 'LOP_DELETE_ROWS'

関心のあるトランザクションのトランザクションIDを取得し、次のような取引を開始したSIDを特定します。

SELECT
    [Transaction SID]
FROM
    fn_dblog(NULL, NULL)
WHERE
    [Transaction ID] = @TranID
AND
    [Operation] = 'LOP_BEGIN_XACT'

次に、SIDからユーザーを識別します。

SELECT
    *
FROM 
    sysusers
WHERE
    [sid] = @SID

編集:指定されたテーブルで削除を見つけるためにすべてをまとめる:

DECLARE @TableName sysname
SET @TableName = 'dbo.Table_1'

SELECT
    u.[name] AS UserName
    , l.[Begin Time] AS TransactionStartTime
FROM
    fn_dblog(NULL, NULL) l
INNER JOIN
    (
    SELECT
        [Transaction ID]
    FROM 
        fn_dblog(NULL, NULL) 
    WHERE
        AllocUnitName LIKE @TableName + '%'
    AND
        Operation = 'LOP_DELETE_ROWS'
    ) deletes
ON  deletes.[Transaction ID] = l.[Transaction ID]
INNER JOIN
    sysusers u
ON  u.[sid] = l.[Transaction SID]

他のヒント

データベースが完全な回復モードにある場合、またはトランザクションログのバックアップがある場合は、サードパーティのログリーダーを使用してこれらを読み取ることができます。

あなたが試すことができます apexsqlログ (プレミアムですが、無料試用版があります)または (無料ですが、SQL 2000のみ)。

SQL Serverデータベースで誰がいくつかのデータを削除したかを知る方法

これには回答されていますが、SQL Serverにはデフォルトのトレースが有効になっており、オブジェクトを削除/変更した人を見つけるために使用できることを追加したいと考えています。

オブジェクトイベント

オブジェクトイベントには以下が含まれます:オブジェクトの変更、作成されたオブジェクト、削除されたオブジェクト

ノート: SQL Serverには、デフォルトで5つのトレースファイルがあり、それぞれ20 MBがあり、これを変更するサポートされている方法は既知の方法はありません。ビジーシステムがある場合、トレースファイルは(数時間以内であっても)速すぎる可能性があり、変更の一部をキャッチできない場合があります。

優れた例を見つけることができます: SQL Serverのデフォルトトレース - パフォーマンスとセキュリティ監査の力

この手順を試して、ログバックアップファイルを照会し、テーブルの列の特定の値がまだ/最後の存在であったログバックアップファイルを見つけることができます。

ユーザーを見つけるには、ログバックアップが最後に存在するかどうかを見つけた後、そのログバックアップまでデータベースを復元してからフォローできます。 マークストーリースミスの答え。

いくつかの前提条件

  • どの列が削除されたかを知っています
  • 完全な回復モデルの下にあり、ログバックアップを取得しています
  • Ola Hallengrenのソリューションを使用する場合など、ログバックアップに日付または識別子があります

免責事項

このソリューションは防水とはほど遠いものであり、さらに多くの作業が必要です。

大規模な環境や、いくつかの小さなテスト以外の環境ではテストされていません。現在の実行はSQL Server 2017ででした。

以下で使用できます 手順 から ムハンマド・イムラン 私がその内容を使用するように変更したこと ログバックアップ ライブデータベースのログの内容の代わりに。

このようにして、技術的には復元を行っていませんが、代わりにログの内容を一時テーブルにダンプします。それはおそらくまだ遅く、バグや問題に対して非常に開かれています。しかし、理論的には機能する可能性があります。

ストアドプロシージャは、文書化されていないものを使用します fn_dump_dblog ログファイルを読み取る機能。


テスト環境

このデータベースを考慮して、いくつかの行を挿入し、2つのログバックアップを取り、3番目のログバックアップですべての行を削除します。

CREATE DATABASE WrongDeletesDatabase
GO
USE WrongDeletesDatabase
GO
BACKUP DATABASE WrongDeletesDatabase TO DISK ='c:\temp\Full.bak'

ALTER DATABASE WrongDeletesDatabase SET RECOVERY FULL
GO

CREATE TABLE dbo.WrongDeletes(ID INT, val varchar(255))

INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (1,'value1')
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log1.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (2,'value2')
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log2.trn'
GO
DELETE FROM dbo.WrongDeletes
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log3.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (3,'value3')
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log4.trn'
GO

手順

ストアドプロシージャを見つけてダウンロードできます ここ.

キャラクターの制限よりも大きいので、ここに追加できませんでした。

これとは別に、手順を実行できるはずです。

手順を実行します

この例として、すべてのログファイルを追加すると(4)ストアドプロシージャに&value1を探している手順を実行します1

EXEC dbo.Recover_Deleted_Data_Proc  @Database_Name= 'WrongDeletesDatabase',
                                    @SchemaName_n_TableName= 'dbo.WrongDeletes', 
                                    @SearchString = 'value1', 
                                    @SearchColumn = 'val',
                                    @LogBackupFolder ='C:\temp\Logs\'

これは私を得る:

ID  val LogFileName
1   value1  c:\temp\Logs\log3.trn
1   value1  c:\temp\Logs\log1.trn

最後に操作がいつでも見つかる場所 value1 起こった、削除 log3.trn.

別の列のあるテーブルを追加して、さらにテストデータをテストします

CREATE TABLE dbo.WrongDeletes2(Wow varchar(255), Anotherval varchar(255),Val3 int)

INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (1,'value1')
INSERT INTO dbo.WrongDeletes2(wOw,Anotherval,Val3)
VALUES ('b','value1',1)
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log1_1.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (2,'value2')
INSERT INTO dbo.WrongDeletes2(wOw,Anotherval,Val3)
VALUES ('c','value2',2)
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log2_1.trn'
GO
DELETE FROM dbo.WrongDeletes
DELETE FROM dbo.WrongDeletes2
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log3_1.trn'
GO
INSERT INTO dbo.WrongDeletes(ID,val)
VALUES (3,'value3')
INSERT INTO dbo.WrongDeletes2(wOw,Anotherval,Val3)
VALUES ('d','value3',3)
GO
BACKUP LOG WrongDeletesDatabase TO DISK = 'c:\temp\Logs\log4_1.trn'
GO

ログファイル名を変更し、手順を再度実行する

EXEC dbo.Recover_Deleted_Data_Proc  @Database_Name= 'WrongDeletesDatabase',
                                    @SchemaName_n_TableName= 'dbo.WrongDeletes', 
                                    @SearchString = 'value1', 
                                    @SearchColumn = 'val',
                                    @LogBackupFolder ='C:\temp\Logs\'

結果

ID  val LogFileName
1   value1  c:\temp\Logs\log1_1.trn
1   value1  c:\temp\Logs\log3_1.trn
1   value1  c:\temp\Logs\log3_1.trn

整数を検索する新しい実行(2) の中に val3 の列 dbo.WrongDeletes2

EXEC dbo.Recover_Deleted_Data_Proc  @Database_Name= 'WrongDeletesDatabase',
                                    @SchemaName_n_TableName= 'dbo.WrongDeletes2', 
                                    @SearchString = '2', 
                                    @SearchColumn = 'Val3',
                                    @LogBackupFolder ='C:\temp\Logs\'

結果

Anotherval  Val3    Wow LogFileName
value2  2   c   c:\temp\Logs\log2.trn
value2  2   c   c:\temp\Logs\log3.trn

申請中 マークストーリースミスの答え

3番目のログファイルで発生したことがわかりました。その時点まで復元しましょう。

USE master
GO
ALTER DATABASE WrongDeletesDatabase SET OFFLINE WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE WrongDeletesDatabase SET ONLINE 
GO
RESTORE DATABASE WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\Full.bak' WITH NORECOVERY,REPLACE
RESTORE LOG WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\log1.trn' WITH NORECOVERY
RESTORE LOG WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\log2.trn' WITH NORECOVERY
RESTORE LOG WrongDeletesDatabase FROM DISK = 'c:\temp\Logs\log3.trn' WITH RECOVERY
GO
USE WrongDeletesDatabase
GO

彼の答えで最後のクエリを実行します

SELECT
    u.[name] AS UserName
    , l.[Begin Time] AS TransactionStartTime
FROM
    fn_dblog(NULL, NULL) l
INNER JOIN
    (
    SELECT
        [Transaction ID]
    FROM 
        fn_dblog(NULL, NULL) 
    WHERE
        AllocUnitName LIKE @TableName + '%'
    AND
        Operation = 'LOP_DELETE_ROWS'
    ) deletes
ON  deletes.[Transaction ID] = l.[Transaction ID]
INNER JOIN
    sysusers u
ON  u.[sid] = l.[Transaction SID]

私のための結果(sysadmin)

UserName    TransactionStartTime
dbo 2019/08/09 17:14:10:450
dbo 2019/08/09 17:14:10:450
ライセンス: CC-BY-SA帰属
所属していません dba.stackexchange
scroll top