This article is the most important part for DBAs and developers.
Sometimes DBAs and developers delete, truncate and drop data objects from the database. So I decided to recover data and objects using the transaction log and LSNs.
This is not as challenging a task to recover the data. However, you may not be aware of the date and the time when the exact data was deleted/truncated and the dropped data objects from the database. I recommend you read my previous tip how to Track Database Transaction Log in SQL Server 2012. This tip will help you to understand the Transaction Log.
Let's create a small Test Environment using the Transaction Log and LSNs using the undocumented function "fn_dblog”.
I assume the database is in full recovery mode. If you want to recover your data and objects I suggest you first use the following procedure on the test environment.
Now I will follow the test environment.
Step 1
Now I will create a database and a table that I will create delete and drop test for as in the following:
- --Create Test DB.
- USE [master];
- GO
- CREATE DATABASE RecoverDB;
- GO
- USE RecoverDB;
- GO
- --Create a table
- CREATE TABLE Employee
- (
- Emp_ID INT IDENTITY(1, 1) ,
- Emp_Name VARCHAR(55) ,
- Emp_Technology VARCHAR(55) ,
- Emp_Salary DECIMAL(10, 2) ,
- Emp_Designation VARCHAR(20) )
- GO
- --Create another table
- CREATE TABLE Personal_Detail
- (
- Emp_ID INT,
- FName VARCHAR(55) ,
- DOB VARCHAR(55) ,
- [Address] VARCHAR(60) ,
- Mobile INT ,
- [State] VARCHAR(60) )
- GO
Now I will take a full backup of the preceding database.
Note: If you want to use an existing database then there is no need to take a new full backup for recovery, you just need the last created full backup of the database.
- -- Create Backup of 'RecoverDB' database.
- USE [Master]
- GO
- BACKUP DATABASE RecoverDB
- TO DISK = 'D:\backup\RecoverDB.BAK'
- GO

Step 3
I have created a database named RecoverDB and a table named Employee and Personal_Detail. Now I will insert a few records in the table.
Note: For an existing database there is no need to do this step.
- SET NOCOUNT ON;
- GO
- USE RecoverDB;
- GO
- --Now Insert data to table Employee
- INSERT INTO Employee
- VALUES ( 'Sumit', 'SQL', 12000, 'SE' )
- , ( 'Ravi', 'ASP.NET', 15000, 'TL' )
- , ( 'Ajay', 'C#', 14000, 'SE' )
- , ( 'vikas', 'JAVA', 22000, 'SSE' )
- , ( 'deepak', 'VB', 18000, 'TH' )
- -- Now Insert data to Personal_Detail
- INSERT INTO Personal_Detail
- VALUES ( 1, 'V.Agarwal', '28-12-1986', 'Noida', 965287985, 'UP' )
- , ( 2, 'S.S.kumar', '02-06-1986', 'delhi', 96548200, 'Delhi' )
- , ( 3, 'Garav.rai', '30-03-1987', 'Noida', 99922535, 'UP' )
- , ( 4, 'A.R.Patak', '19-12-1986', 'Rampur', 808563131, 'UP' )
- , ( 5, 'R.shah', '25-09-1985', 'Delhi', 954651423, 'Delhi' )
- GO
Step 4
Now I will delete some rows from the table named Employee and truncate data from the table Personal_Detail.
- -- delete data from Employee table.
- USE RecoverDB
- GO
- DELETE FROM Employee
- WHERE Emp_ID <3
- GO
- -- truncate data from Personal_Detail table.
- TRUNCATE TABLE Personal_Detail
- GO
Step 5
Now I will find the deleted and truncated rows using the Transaction log using the undocumented function "fn_dblog”. Run the code below to get information about all the deleted transactions.
- SELECT
- [Current LSN],
- Operation,
- [Transaction ID],
- [Begin Time],
- [Transaction Name],
- [Transaction SID],
- AllocUnitName
- FROM
- fn_dblog (NULL, NULL)
Step 6
Now I will take the deleted and truncated Transaction IDs like: Deleted-’0000:000004ea’,
Truncated: '0000:000004eb'. You can see that in the preceding screen and Find the LSN .
- --For Delete
- SELECT
- [Current LSN],
- Operation,
- [Transaction ID],
- [Begin Time],
- [Transaction Name],
- [Transaction SID],
- AllocUnitName
- FROM
- fn_dblog (NULL, NULL)
- WHERE
- [Transaction ID] = '0000:000004ea'
- AND
- [Operation] = 'LOP_BEGIN_XACT'
- GO
- -- for truncate
- SELECT
- [Current LSN],
- Operation,
- [Transaction ID],
- [Begin Time],
- [Transaction Name],
- [Transaction SID],
- AllocUnitName
- FROM
- fn_dblog (NULL, NULL)
- WHERE
- [Transaction ID] = '0000:000004eb'
- AND
- [Operation] = 'LOP_BEGIN_XACT'
RaveendrabjPosted Jul 30, 2022, 12:52 PM
Good help for me!
DEEPAK GUPTAPosted Dec 2, 2015, 1:32 PM
Hello Shivom We have tried to recover the deleted data in the same way as you documented but my copy database moves in restoring mode because we got the error "The specified STOPAT time is too early. All or part of the database is already rolled forward beyond that point." and now I am not able to see the deleted record in "fn_dblog" function. Please help us why so?
Shivom AgarwalPosted Feb 1, 2015, 10:52 PM
thanks sandeep
sandeep nairPosted Jan 23, 2015, 1:57 AM
Good article..so detailed. Keep up the good work.
Anupam SinghPosted Jul 30, 2014, 6:17 AM
An excellent article Shivom. Thanx for sharing .