it-swarm-eu.dev

Jak zjistit, kdo odstranil některá data SQL Server

Můj šéf měl včera dotaz od zákazníka s dotazem, jak by mohl zjistit, kdo odstranil některá data v jejich databázi SQL Server (pokud je to důležité, jedná se o expresní vydání).

Myslel jsem, že to lze najít z protokolu transakcí (za předpokladu, že nebyl zkrácen) - je to správné? A pokud ano, jak se vlastně snažíte najít tyto informace?

29
Matt Wilko

Nezkoušel jsem fn_dblog na Express, ale pokud je k dispozici, následující vám umožní operace odstranění:

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

Vezměte ID transakce pro transakce, které vás zajímají, a identifikujte SID, které transakci zahájilo:

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

Poté identifikujte uživatele ze SID:

SELECT
    *
FROM 
    sysusers
WHERE
    [sid] = @SID

Úpravy: Spojte všechny dohromady a najděte mazání v určené tabulce:

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

Pokud je databáze v úplném režimu obnovy nebo pokud máte zálohy protokolu transakcí, můžete je zkusit přečíst pomocí čteček protokolu třetích stran.

Můžete zkusit ApexSQL Log (prémiový, ale má zkušební verzi zdarma) nebo SQL Log Rescue (zdarma, ale pouze SQL 2000).

3
Tony Melanik

jak mohli zjistit, kdo odstranil některá data v jejich databázi SQL Server

Přestože je zodpovězeno, chtěli jsme přidat, že SQL Server má povoleno výchozí trasování a lze jej použít ke zjištění, kdo zrušil/změnil objekty.

Události objektu

Události objektu zahrnují: Object Altered, Object Created a Object Deleted

poznámka: SQL Server ve výchozím nastavení obsahuje 5 trasovacích souborů, každý o 20 MB a není známa žádná podporovaná metoda změny. Pokud máte zaneprázdněný systém, soubory trasování se mohou převrátit příliš rychle (i během několika hodin) a některé změny pravděpodobně nebudete moci zachytit.

Vynikající příklad lze nalézt: Výchozí trasování v SQL Server - výkon auditování výkonu a zabezpečení

3
Kin Shah

Můžete zkusit tento postup k dotazu na záložní soubory protokolu a zjistit, ve kterém záložním souboru (souborech) protokolu byla/stále byla konkrétní hodnota sloupce tabulky.

Chcete-li najít uživatele, po nalezení zálohy protokolu, která naposledy existovala, můžete obnovit databázi až do zálohy protokolu a poté následovat odpověď Mark Storey-Smith .

Některé předpoklady

  • vědět, jaké hodnoty byly ze sloupců odstraněny
  • Jsou pod úplným modelem obnovy a provádějí zálohy protokolu
  • máte v zálohách protokolu data nebo identifikátory, například při použití řešení Ola Hallengren

Zřeknutí se odpovědnosti

Toto řešení zdaleka není vodotěsné a je třeba do něj dostat mnohem více práce.

Nebyl testován ve velkém měřítku nebo dokonce v jakémkoli prostředí kromě několika malých testů. Aktuální běh byl na serveru SQL Server 2017.

Můžete použít níže procedura z Muhammad Imran , kterou jsem upravil, aby pracoval s obsahem záloh protokolu namísto obsahu protokolu živé databáze.

Tímto způsobem technicky neděláte obnovení, ale místo toho uložíte obsah protokolu do dočasné tabulky. Pravděpodobně bude stále pomalý a je velmi otevřený chybám a problémům. Ale mohlo by to fungovat teoreticky ™.

Uložená procedura používá nezdokumentovanou fn_dump_dblog funkce pro čtení souborů protokolu.


Testovací prostředí

Zvažte tuto databázi, do které vložíme několik řádků, vezmeme 2 zálohy protokolu a na třetí zálohu zálohy odstraníme všechny řádky.

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

Postup

Uloženou proceduru můžete najít a stáhnout zde .

Nemohl jsem ho sem přidat, protože je větší než omezení počtu znaků a tuto odpověď by byl ještě méně jasný, než je.

Kromě toho byste měli být schopni spustit proceduru.

Spuštění procedury

Příklad toho, když přidám všechny své soubory protokolu (4) do uložené procedury a spusťte proceduru hledající hodnotu1

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

To mě dostane:

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

Kde najdeme, kdy naposledy byla operace na value1 se stalo, smazání v log3.trn.

Několik dalších testovacích dat, přidání tabulky s různými sloupci

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

Změna názvů souborů protokolu a provedení procedury znovu

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

Výsledek

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

Nový běh, hledání celého čísla (2) v val3 sloupec dbo.WrongDeletes2

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

Výsledek

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

Použití Mark Storey-Smith odpověď

Nyní víme, že se to stalo ve třetím souboru protokolu, obnovme se až do tohoto bodu:

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

Spuštění posledního dotazu v jeho odpovědi

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]

Výsledek pro mě (sysadmin)

UserName    TransactionStartTime
dbo 2019/08/09 17:14:10:450
dbo 2019/08/09 17:14:10:450
1
Randi Vertongen