Domanda

Il mio capo ha avuto una query da un cliente ieri chiedendo come avrebbero potuto scoprire chi cancellato alcuni dati nel loro database SQL Server (è l'edizione espressa se quello che conta).

Ho pensato che questo potrebbe essere trovato dal log delle transazioni (purché non fosse stato troncato) - è corretto? E se sì, come si fa a realtà fare per trovare queste informazioni?

È stato utile?

Soluzione

Non ho provato fn_dblog su Express, ma se è disponibile di seguito vi darà le operazioni di eliminazione:

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

Prendere l'ID di transazione per le transazioni che ti interessa e identificare il SID che ha avviato la transazione con:

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

Quindi identificare l'utente dal SID:

SELECT
    *
FROM 
    sysusers
WHERE
    [sid] = @SID

Modifica: Portare che tutti insieme per trovare le eliminazioni su una tabella specificata:

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]

Altri suggerimenti

Se il database è in modalità di recupero completo o se si dispone di backup del log delle transazioni si può provare a leggere questi lettori di log di terze parti che utilizzano.

Si può provare a ApexSQL Log (premio ma ha una versione di prova gratuita) o SQL Log Rescue (gratuito ma sql 2000).

come avrebbero potuto scoprire chi cancellato alcuni dati nel loro database SQL Server

Anche se questa risposta, ha voluto aggiungere che SQL Server ha una traccia di default abilitato e può essere utilizzato per scoprire chi è sceso / alterato gli oggetti.

eventi Oggetto

eventi oggetto includono: Object Altered, oggetto creato e oggetto eliminato

Nota: di SQL Server per impostazione predefinita ha 5 file di traccia, 20 MB ciascuno e non c'è è noto metodo supportato per cambiare questo. Se si dispone di un sistema occupato, i file di traccia possono rotolare troppo veloce (anche poche ore) e potrebbe non essere in grado di catturare alcuni dei cambiamenti.

Eccellente esempio può essere trovato: la traccia di default in SQL Server - la potenza di prestazioni e sicurezza auditing

Si potrebbe provare questa procedura per interrogare i file di backup del registro e di trovare in cui il file di log di backup (s) uno specifico valore di una colonna di una tabella era ancora / ultimo regalo.

Per trovare l'utente, dopo aver trovato in quello che registro di backup l'ultimo valore esiste, è possibile ripristinare un database fino a quel backup del registro e poi seguire Mark Storey-Smith 's risposta.

Alcuni prerequisiti

  • so cosa valori da cui colonne sono stati cancellati
  • sono sotto il modello di recupero completo e stanno prendendo i backup del log
  • avete date o identificatori nel backup del log, ad esempio quando si utilizza Ola La soluzione di Hallengren

responsabilità

Questa soluzione è tutt'altro che impermeabile, e molto di più esigenze di lavoro per andare in esso.

E non è stato testato su ambienti di grandi dimensioni, o anche qualsiasi ambiente a parte alcuni piccoli test. esecuzione corrente era in SQL Server 2017.

Si potrebbe usare sotto procedura da Muhammad Imran che ho modificato per lavorare con i contenuti di backup log al posto del contenuto del registro di un database dal vivo.

In questo modo non si sta facendo tecnicamente ripristini, ma invece il dumping il contenuto del registro in una tabella temporanea. Sarà probabilmente ancora lento, ed è molto aperto a bug e problemi. Ma potrebbe funzionare, in teoria ™.

La stored procedure utilizza la funzione non documentata fn_dump_dblog per leggere i file di log.


ambiente di test

Si consideri questo database, dove inseriamo alcune righe, prendere 2 backup del log, e al terzo backup del log che elimina tutte le righe.

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

La procedura

È possibile trovare e scaricare la stored procedure qui .

Non ho potuto inserirlo qui dato che è più grande del limite di caratteri, e renderebbe questa risposta ancora meno chiara di quanto non sia.

Oltre a questo, si dovrebbe essere in grado di eseguire la procedura.

Esecuzione della procedura

Un esempio di questo, quando aggiungo tutti i miei file di log (4) alla stored procedure e eseguire la procedura di ricerca di valore1

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

Questo mi fa:

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

Dove possiamo trovare quando l'ultima volta che un'operazione su value1 accaduto, la cancellazione in log3.trn.

Alcuni dati di test più, l'aggiunta di una tabella con diverse colonne

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

Modifica dei nomi dei file di registro e di eseguire la procedura di nuovo

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

Risultato

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

Una nuova pista, alla ricerca di numero intero (2) nella colonna di 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\'

Risultato

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

Applicazione risposta Mark Storey-Smith s '

Ora sappiamo che è accaduto nel terzo file di log, cerchiamo di ripristinare fino a quel punto:

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

Esecuzione l'ultima query nella sua risposta

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]

Risultato per me (sysadmin)

UserName    TransactionStartTime
dbo 2019/08/09 17:14:10:450
dbo 2019/08/09 17:14:10:450
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top