it-swarm.com.de

So finden Sie heraus, wer einige SQL Server-Daten gelöscht hat

Mein Chef hatte gestern eine Anfrage von einem Kunden, wie er herausfinden könne, 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 wurde nicht abgeschnitten) - ist das richtig? Und wenn ja, wie gehen Sie tatsächlich vor, um diese Informationen herauszufinden?

29
Matt Wilko

Ich habe fn_dblog in Express nicht ausprobiert, aber wenn es verfügbar ist, erhalten Sie folgende Löschvorgänge:

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 die SID, die die Transaktion initiiert hat, mit:

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

Identifizieren Sie dann den Benutzer anhand der SID:

SELECT
    *
FROM 
    sysusers
WHERE
    [sid] = @SID

Bearbeiten: Bringen Sie alles zusammen, um Löschvorgänge in einer angegebenen 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]
35

Wenn sich die Datenbank im vollständigen Wiederherstellungsmodus befindet oder wenn Sie Transaktionsprotokollsicherungen haben, können Sie versuchen, diese mit Protokolllesern von Drittanbietern zu lesen.

Sie können versuchen ApexSQL Log (Premium, hat aber eine kostenlose Testversion) oder SQL Log Rescue (kostenlos, aber nur SQL 2000).

3
Tony Melanik

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

Obwohl dies beantwortet wird, wollte ich hinzufügen, dass in SQL Server eine Standardablaufverfolgung aktiviert ist und damit ermittelt werden kann, wer die Objekte gelöscht/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 Tracedateien mit jeweils 20 MB, und es ist keine unterstützte Methode zum Ändern bekannt. Wenn Sie ein ausgelastetes System haben, werden die Tracedateien möglicherweise viel zu schnell (sogar innerhalb von Stunden) übertragen, und Sie können möglicherweise einige der Änderungen nicht erfassen.

Ein hervorragendes Beispiel finden Sie hier: Die Standardablaufverfolgung in SQL Server - Leistungsfähigkeit und Sicherheitsüberwachung

3
Kin Shah

Sie können dieses Verfahren ausprobieren, um die Protokollsicherungsdateien abzufragen und festzustellen, in welchen Protokollsicherungsdateien ein bestimmter Wert einer Spalte einer Tabelle noch vorhanden/zuletzt vorhanden war.

Um den Benutzer zu finden, können Sie, nachdem Sie in welcher Protokollsicherung den zuletzt vorhandenen Wert gefunden haben, eine Datenbank bis zu dieser Protokollsicherung wiederherstellen und dann der Antwort von Mark Storey-Smith folgen.

Einige Voraussetzungen

  • wissen, welche Werte aus welchen Spalten gelöscht wurden
  • Befinden sich unter dem vollständigen Wiederherstellungsmodell und führen Protokollsicherungen durch
  • ihre Protokollsicherungen enthalten Daten oder Kennungen, z. B. bei Verwendung der Lösung von Ola Hallengren

Haftungsausschluss

Diese Lösung ist alles andere als wasserdicht und es muss noch viel mehr Arbeit investiert werden.

Es wurde nicht in großen Umgebungen oder sogar in anderen Umgebungen getestet, abgesehen von einigen kleinen Tests. Der aktuelle Lauf war auf SQL Server 2017.

Sie können unten procedure from Muhammad Imran verwenden, das ich geändert habe, um mit dem Inhalt von Protokollsicherungen zu arbeiten anstelle des Inhalts des Protokolls einer Live-Datenbank.

Auf diese Weise führen Sie technisch gesehen keine Wiederherstellungen durch, sondern sichern den Protokollinhalt in einer temporären Tabelle. Es wird wahrscheinlich immer noch langsam sein und ist sehr offen für Fehler und Probleme. Aber theoretisch könnte es funktionieren.

Die gespeicherte Prozedur verwendet das undokumentierte fn_dump_dblog Funktion zum Auslesen der Protokolldateien.


Testumgebung

Betrachten Sie diese Datenbank, in der wir einige Zeilen einfügen, zwei Protokollsicherungen durchführen und bei 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

Die Prozedur

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

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

Abgesehen davon sollten Sie in der Lage sein, die Prozedur auszuführen.

Ausführen der Prozedur

Ein Beispiel dafür, wenn ich alle meine Protokolldateien hinzufüge (4) zur gespeicherten Prozedur und führen Sie die Prozedur aus, die nach Wert1 sucht

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 können wir finden, wann das letzte Mal eine Operation auf value1 passiert, das Löschen in log3.trn.

Weitere Testdaten, Hinzufügen einer Tabelle mit verschiedenen Spalten

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, der nach der Ganzzahl sucht (2) in dem val3 Spalte 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

Anwenden von Mark Storey-Smith 's Antwort

Wir wissen jetzt, dass es in der dritten Protokolldatei passiert ist. Lassen Sie uns bis zu diesem Punkt 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 Abfrage 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
1
Randi Vertongen