Anda bisa mencoba prosedur ini untuk meminta 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 jawaban Mark Storey-Smith .
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
Penolakan
Solusi ini jauh dari tahan air, dan masih banyak pekerjaan yang harus dilakukan.
Itu 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 prosedur di bawah ini dari Muhammad Imran yang saya modifikasi untuk bekerja 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 dalam tabel sementara. Mungkin masih lambat, dan sangat terbuka untuk bug dan masalah. Tapi itu bisa berhasil, dalam teori ™.
Prosedur tersimpan menggunakan fn_dump_dblog
fungsi tidak berdokumen untuk membacakan file log.
Lingkungan pengujian
Pertimbangkan basis data ini, tempat kami memasukkan beberapa baris, ambil 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 value1
terjadi, penghapusan dalam log3.trn
.
Beberapa data uji lagi, menambahkan tabel dengan kolom 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
Jalankan baru, mencari integer ( 2
) di val3
kolomdbo.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 jawaban Mark Storey-Smith
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