it-swarm.asia

Cara mengetahui siapa yang menghapus beberapa data SQL Server

Bos saya memiliki permintaan dari pelanggan kemarin yang menanyakan bagaimana mereka bisa mengetahui siapa yang menghapus beberapa data dalam database SQL Server mereka (ini adalah edisi kilat jika itu penting).

Saya pikir ini dapat ditemukan dari log transaksi (asalkan belum terpotong) - apakah ini benar? Dan jika demikian, bagaimana Anda benar-benar mencari informasi ini?

29
Matt Wilko

Saya belum mencoba fn_dblog pada Express tetapi jika tersedia, yang berikut ini akan memberi Anda operasi penghapusan:

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

Ambil ID transaksi untuk transaksi yang Anda minati dan identifikasi SID yang memulai transaksi dengan:

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

Kemudian identifikasi pengguna dari SID:

SELECT
    *
FROM 
    sysusers
WHERE
    [sid] = @SID

Sunting: Membawa semuanya untuk menemukan penghapusan pada tabel yang ditentukan:

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

Jika database dalam mode pemulihan penuh atau jika Anda memiliki cadangan log transaksi, Anda dapat mencoba membacanya menggunakan pembaca log pihak ketiga.

Anda dapat mencoba ApexSQL Log (premium tetapi memiliki percobaan gratis) atau SQL Log Rescue (gratis tetapi hanya 2000 sql).

3
Tony Melanik

bagaimana mereka bisa mengetahui siapa yang menghapus beberapa data dalam database SQL Server mereka

Meskipun ini dijawab, ingin menambahkan bahwa SQL Server memiliki jejak default yang diaktifkan dan dapat digunakan untuk mencari tahu siapa yang menjatuhkan/mengubah objek.

Acara objek

Acara objek meliputi: Objek Diubah, Objek Dibuat dan Objek Dihapus

catatan: SQL Server secara default memiliki 5 jejak file, masing-masing 20 MB dan tidak ada metode yang didukung untuk mengubah hal ini. Jika Anda memiliki sistem yang sibuk, file jejak mungkin bergulir terlalu cepat (bahkan dalam beberapa jam) dan Anda mungkin tidak dapat menangkap beberapa perubahan.

Contoh yang sangat baik dapat ditemukan: Jejak default di SQL Server - kekuatan audit kinerja dan keamanan

3
Kin Shah

Anda bisa mencoba prosedur ini untuk menanyakan file cadangan log dan menemukan di mana file cadangan log nilai tertentu dari kolom tabel masih ada/terakhir hadir.

Untuk menemukan pengguna, setelah Anda menemukan dalam cadangan log apa nilai terakhir ada, Anda dapat mengembalikan database hingga cadangan log itu dan kemudian ikuti Mark Storey-Smith jawaban.

Beberapa prasyarat

  • tahu nilai apa dari kolom mana yang dihapus
  • Sedang dalam model pemulihan penuh dan sedang mengambil cadangan log
  • anda memiliki tanggal atau pengidentifikasi dalam cadangan log Anda, seperti ketika menggunakan solusi Ola Hallengren

Penafian

Solusi ini jauh dari tahan air, dan masih banyak pekerjaan yang harus dilakukan.

Ini belum diuji pada lingkungan skala besar, atau bahkan lingkungan apa pun selain dari beberapa tes kecil. Jalankan saat ini pada SQL Server 2017.

Anda dapat menggunakan di bawah prosedur dari Muhammad Imran yang saya modifikasi agar berfungsi dengan isi cadangan log alih-alih isi dari log basis data langsung.

Dengan cara ini Anda secara teknis tidak melakukan pemulihan, tetapi membuang konten log di tabel sementara. Mungkin masih lambat, dan sangat terbuka untuk bug dan masalah. Tapi itu bisa berhasil, dalam teori ™.

Prosedur tersimpan menggunakan fungsi fn_dump_dblog Yang tidak berdokumen untuk membaca file log.


Lingkungan pengujian

Pertimbangkan basis data ini, tempat kami menyisipkan beberapa baris, mengambil 2 cadangan log, dan pada cadangan log ketiga kami menghapus semua baris.

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

Prosedur

Anda dapat menemukan dan mengunduh prosedur tersimpan di sini .

Saya tidak dapat menambahkannya di sini karena lebih besar dari batas karakter, dan akan membuat jawaban ini lebih tidak jelas daripada sebelumnya.

Terlepas dari ini, Anda harus dapat menjalankan prosedur.

Menjalankan prosedur

Contoh dari ini, ketika saya menambahkan semua file log saya (4) Ke prosedur tersimpan & menjalankan prosedur mencari value1

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

Ini membuat saya:

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

Di mana kami dapat menemukan kapan operasi terakhir pada value1 Terjadi, hapus pada log3.trn.

Beberapa data uji lagi, menambahkan tabel dengan kolom yang berbeda

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

Mengubah nama file log & menjalankan prosedur lagi

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

Hasil

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

Proses baru, mencari integer (2) Di kolom val3 Pada dbo.WrongDeletes2

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

Hasil

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

Menerapkan Mark Storey-Smith jawaban

Kita tahu sekarang bahwa itu terjadi pada file log ketiga, mari kita pulihkan sampai titik itu:

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

Menjalankan kueri terakhir dalam jawabannya

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]

Hasil untuk saya (sysadmin)

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