Frage

Mein Chef hatte gestern eine Abfrage von einem Kunden und fragte, wie er herausfinden kann, wer einige Daten in seiner SQL Server -Datenbank gelöscht hat (es ist die Express Edition, wenn dies wichtig ist).

Ich dachte, dies könnte aus dem Transaktionsprotokoll gefunden werden (vorausgesetzt, es war nicht verkürzt worden) - ist das richtig? Und wenn ja, wie können Sie diese Informationen tatsächlich herausfinden?

War es hilfreich?

Lösung

Ich habe fn_dblog auf Express nicht ausprobiert, aber wenn es verfügbar ist, erhalten Sie nach Folgen von Löschen von Vorgängen:

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

Nehmen Sie die Transaktions -ID für Transaktionen, an denen Sie interessiert sind, und identifizieren Sie den SID, der die Transaktion mit:

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

Identifizieren Sie dann den Benutzer aus dem SID:

SELECT
    *
FROM 
    sysusers
WHERE
    [sid] = @SID

Bearbeiten: Bringen Sie das alles zusammen, um Deletten in einer bestimmten Tabelle zu finden:

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]

Andere Tipps

Wenn die Datenbank im vollständigen Wiederherstellungsmodus ist oder über Transaktionsprotokollsicherungen verfügt, können Sie versuchen, diese mit Lesern von Drittanbietern zu lesen.

Du kannst es versuchen ApexSQL -Protokoll (Prämie, hat aber eine kostenlose Testversion) oder SQL Log Rescue (Nur frei, aber nur SQL 2000).

Wie sie herausfinden konnten, wer einige Daten in ihrer SQL Server -Datenbank gelöscht hat

Obwohl dies beantwortet wird, wollte der SQL -Server eine Standardverfolgung aktiviert und es kann verwendet werden, um herauszufinden, wer die Objekte fallen gelassen/geändert hat.

Objektereignisse

Zu den Objektereignissen gehören: Objekt geändert, Objekt Erstellt und Objekt gelöscht

Hinweis: SQL Server verfügt standardmäßig über 5 Trace -Dateien, jeweils 20 MB, und es gibt keine unterstützte Methode, um dies zu ändern. Wenn Sie ein geschäftiges System haben, können die Trace -Dateien (sogar innerhalb von Stunden) viel zu schnell überrollen, und Sie können möglicherweise nicht einige der Änderungen fangen.

Hervorragendes Beispiel kann gefunden werden: Die Standardverfolgung in SQL Server - die Leistung der Leistung und Sicherheitsprüfung

Sie können diese Prozedur versuchen, die Protokollsicherungsdateien abzufragen und zu finden, in welcher Protokollsicherungsdatei (n) ein bestimmter Wert einer Spalte einer Tabelle noch vorhanden war.

Um den Benutzer zu finden, können Sie eine Datenbank bis zu dieser Protokollsicherung wiederherstellen und dann folgen Mark Storey-SmithAntwort.

Einige Voraussetzungen

  • Wissen Sie, welche Werte aus den Spalten gelöscht wurden
  • Befinden sich unter dem vollständigen Wiederherstellungsmodell und nehmen Protokollsicherungen vor
  • Sie haben Daten oder Kennungen in Ihren Protokollsicherungen, beispielsweise bei der Verwendung von Ola Hallengrens Lösung

Haftungsausschluss

Diese Lösung ist alles andere als wasserdicht, und es muss noch viel mehr Arbeit in sie eingehen.

Es wurde weder in großen Umgebungen noch Umgebungen getestet, abgesehen von einigen kleinen Tests. Der aktuelle Lauf war auf SQL Server 2017.

Sie könnten unten verwenden Verfahren aus Muhammad Imran dass ich geändert habe, um mit dem Inhalt von zu arbeiten Protokollsicherungen Anstelle des Inhalts eines Live -Datenbankprotokolls.

Die gespeicherte Prozedur verwendet die undokumentierte fn_dump_dblog Funktion zum Lesen der Protokolldateien.


Testumgebung

Betrachten Sie diese Datenbank, in der wir einige Zeilen einfügen, 2 Protokollsicherungen nehmen und auf der dritten Protokollsicherung alle Zeilen löschen.

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

Das Verfahren

Sie können die gespeicherte Prozedur finden und herunterladen hier.

Ich konnte es hier nicht hinzufügen, da es größer ist als die Charakterlimit und würde diese Antwort noch weniger klar machen als es ist.

Abgesehen davon sollten Sie in der Lage sein, das Verfahren auszuführen.

Ausführen des Verfahrens

Ein Beispiel dafür, wenn ich alle meine Protokolldateien hinzufüge (4) in die gespeicherte Prozedur und führen Sie das Verfahren aus, die nach Wert 1 suchen1

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

Das bringt mich:

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

Wo wir finden können, wenn das letzte Mal eine Operation eingeschaltet wird value1 passiert, das lösche in log3.trn.

Einige weitere Testdaten, die eine Tabelle mit verschiedenen Spalten hinzufügen

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

Ändern der Protokolldateinamen und erneutes Ausführen der Prozedur

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

Ergebnis

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

Ein neuer Lauf, auf der Suche nach der Ganzzahl (2) in dem val3 Säule von dbo.WrongDeletes2

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

Ergebnis

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

Bewirbt sich Mark Storey-SmithAntwort

Wir wissen jetzt, dass es in der dritten Protokolldatei passiert ist. Lassen Sie uns bis zu diesem Zeitpunkt wiederherstellen:

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

Die letzte Frage in seiner Antwort ausführen

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]

Ergebnis für mich (sysadmin)

UserName    TransactionStartTime
dbo 2019/08/09 17:14:10:450
dbo 2019/08/09 17:14:10:450
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top