TRANSACTION LOG BACKUP and RESTORE SEQUENCE: Myths & Truths
In a recent issue with a customer, I came across a strange SQL belief (or say a DBA Myth) regarding SQL Server Transaction Logs Backup/Restore. Let me explain you what was the scenario and then let’s try attempting to break the myth with quick testing.
SCENERIO:
- Customer is taking FULL and TRANSACTION LOG (T-Log) backup of a critical database
- Backup files are maintained on Disk in sequential order
- Due to a hardware failure, the database got crashed and customer decided to recover from the backups
- Due to an another issue (let’s assume) the most recent FULL backup file is lost and he now only has 1st FULL backup and successive T-Log backups
- Customer is not sure if he will be able to perform point-in-time recovery ß “THE MYTH”
EXPLANATION:
Simple answer to above scenario is: POINT-IN-TIME-RECOVERY can still be performed.
Here’s Why:
A continuous sequence of T-Log backups is tied by a ‘Log Chain’, which starts with a FULL backup. Now, unless we run anything explicitly that breaks the log-chain (Ex., running BACKUP log TRUNCATE_ONLY* or by switching to SIMPLE recovery model), the existing chain remains intact. With the log chain intact, you can restore your database from any FULL database backup in the media set, followed by all subsequent T-Log backups to the point of failure.
TESTING: THE WATERS
To understand the scenario, let’s do some hands-on with BACKUP/RECOVERY using FULL and T-LOG backups
=====================================================================
--CREATE A NEW DATABASE “SAMPLLE_DB” IN FULL RECOVERY MODEL
=====================================================================
Use Master
GO
CREATE DATABASE [SAMPLE_DB] ON PRIMARY
( NAME = N'SAMPLE_DB', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\SAMPLE_DB.mdf' ,
SIZE = 2048KB , FILEGROWTH = 1024KB )
LOG ON
( NAME = N'SAMPLE_DB_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\SAMPLE_DB_log.ldf' ,
SIZE = 1024KB , FILEGROWTH = 10%)
GO
EXEC dbo.sp_dbcmptlevel @dbname=N'SAMPLE_DB', @new_cmptlevel=90
GO
ALTER DATABASE [SAMPLE_DB] SET RECOVERY FULL
GO
=====================================================================
=====================================================================
--PERFORM MULTIPLE BACKUPS (FULL and T-LOG)
=====================================================================
--Take a FULL database backup (This is a starting point of the backup set and is mandatory to have before you can initiate T-Log backup)
BACKUP DATABASE [SAMPLE_DB] TO DISK = N'D:\Backup\DB_FULL.bak'
WITH NOFORMAT, NOINIT, NAME = N'SAMPLE_DB-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--Create a TEST table
Use [SAMPLE_DB]
GO
CREATE TABLE dbo.Table_1
(
Name varchar(50) NULL
) ON [PRIMARY]
GO
--Insert a 1st Row in TEST table
Insert into dbo.Table_1 values ('Rob')
GO
--Take 1st T-LOG backup.
BACKUP LOG [SAMPLE_DB] TO DISK = N'D:\Backup\SAMPLE_DB-TLog1.trn'
WITH NOFORMAT, NOINIT, NAME = N'SAMPLE_DB-Transaction Log Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--Insert a 2nd Row in TEST table
Insert into dbo.Table_1 values ('Bob')
GO
--Take 2nd T-LOG backup.
BACKUP LOG [SAMPLE_DB] TO DISK = N'D:\Backup\SAMPLE_DB-TLog2.trn'
WITH NOFORMAT, NOINIT, NAME = N'SAMPLE_DB-Transaction Log Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--Insert a 3rd Row in TEST table
Insert into dbo.Table_1 values ('Marry')
GO
--Take 2nd FULL database backup
BACKUP DATABASE [SAMPLE_DB] TO DISK = N'D:\Backup\DB_FULL_2.bak'
WITH NOFORMAT, NOINIT, NAME = N'SAMPLE_DB-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--Insert a 4th Row in TEST table
Insert into dbo.Table_1 values ('Suzanne')
GO
--Take 3rd T-LOG backup (Note: This we are taking after 2nd FULL BACKUP)
BACKUP LOG [SAMPLE_DB] TO DISK = N'D:\Backup\SAMPLE_DB-TLog3.trn'
WITH NOFORMAT, NOINIT, NAME = N'SAMPLE_DB-Transaction Log Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--Just a quick check on number of rows in table dbo.Table_1
Use SAMPLE_DB
GO
Select * from dbo.Table_1
GO
Name
--------------------------------------------------
Rob
Bob
Marry
Suzanne
(4 row(s) affected)
=====================================================================
--RESTORE MULTIPLE BACKUPS (HEADER ONLY) TO VERIFY THE Log Chain
=====================================================================
--RESTORE 1ST FULL database backup with HEADERONLY
RESTORE HEADERONLY FROM DISK = 'D:\Backup\DB_FULL.bak'
FirstLSN LastLSN CheckpointLSN DatabaseBackupLSN BeginsLogChain
--------------------------------------- --------------------------------------- --------------------------------------- ----------------- --------------
20000000006300037 20000000008100001 20000000006300037 0 0
For 1st FULL Backup, FirstLSN is 20000000006300037 and LastLSN is 20000000008100001. Also BeginsLogChain is 0. This is staring Log Chain
--RESTORE 1st T-Log backup with HEADERONLY
RESTORE HEADERONLY FROM DISK = 'D:\Backup\SAMPLE_DB-TLog1.trn'
FirstLSN LastLSN CheckpointLSN DatabaseBackupLSN BeginsLogChain
--------------------------------------- --------------------------------------- --------------------------------------- ----------------- --------------
20000000006300037 20000000009900001 20000000006300037 20000000006300037 1
For 2nd T-LOG Backup, FirstLSN is 20000000006300037, LastLSN is 20000000009900001. BeginsLogChain bit is 1, which indicates that this is first in log chain
--RESTORE 2st T-Log backup with HEADERONLY
RESTORE HEADERONLY FROM DISK = 'D:\Backup\SAMPLE_DB-TLog2.trn'
FirstLSN LastLSN CheckpointLSN DatabaseBackupLSN BeginsLogChain
--------------------------------------- --------------------------------------- --------------------------------------- ----------------- --------------
20000000009900001 20000000010000001 20000000006300037 20000000006300037 0
For 2nd T-LOG Backup, FirstLSN is 20000000009900001, which is LastLSN for 1st T-Log backup and can be applied over 1nd T-lOG backup
-- RESTORE 2nd FULL Backup with HEADERONLY
RESTORE HEADERONLY FROM DISK = 'D:\Backup\DB_FULL_2.bak'
FirstLSN LastLSN CheckpointLSN DatabaseBackupLSN BeginsLogChain
--------------------------------------- --------------------------------------- --------------------------------------- ----------------- --------------
20000000010300158 20000000016800001 20000000010300158 20000000006300037 0
For 2nd FULL Backup, FirstLSN is 20000000010300158. This FULL backup is not breaking LSN chain
--RESTORE 3rd T-Log backup with HEADERONLY
RESTORE HEADERONLY FROM DISK = 'D:\Backup\SAMPLE_DB-TLog3.trn'
FirstLSN LastLSN CheckpointLSN DatabaseBackupLSN BeginsLogChain
--------------------------------------- --------------------------------------- --------------------------------------- ----------------- --------------
20000000010000001 20000000017500001 20000000010300158 20000000010300158 0
For 3rd T-LOG Backup, FirstLSN is 20000000010000001 which is LastLSN for 2nd T-LOG backup and can be applied over 2nd T-lOG backup.
=====================================================================
--RESTORE MULTIPLE BACKUPS (THIS TIME DOING IT ACTUALLY!!)
=====================================================================
-- Restore 1st FULL Backup with NORECOVERY
RESTORE DATABASE [SAMPLE_RESTORED] FROM DISK = N'D:\Backup\DB_FULL.bak'
WITH FILE = 1,
MOVE N'SAMPLE_DB' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\SAMPLE_RESTORED.mdf',
MOVE N'SAMPLE_DB_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\SAMPLE_RESTORED_1.ldf',
NORECOVERY, NOUNLOAD, STATS = 10
GO
-- Restore 1st T-Log Backup with NORECOVERY
RESTORE LOG [SAMPLE_RESTORED] FROM DISK = N'D:\Backup\SAMPLE_DB-TLog1.trn'
WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 10
GO
-- Restore 2nd T-Log Backup with NORECOVERY
RESTORE LOG [SAMPLE_RESTORED] FROM DISK = N'D:\Backup\SAMPLE_DB-TLog2.trn'
WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 10
GO
-- NOTE: Here, I'M SKIPPING THE 2nd FULL BACKUP HERE
-- Restore 3rd T-Log Backup with RECOVERY (as this is the last T-Log backup in the chain)
RESTORE LOG [SAMPLE_RESTORED] FROM DISK = N'D:\Backup\SAMPLE_DB-TLog3.trn'
WITH FILE = 1, RECOVERY, NOUNLOAD, STATS = 10
GO
--- Moment of Truth, Lets check the number of rows in TEST table
Use SAMPLE_RESTORED
GO
Select * from dbo.Table_1
GO
Name
--------------------------------------------------
Rob
Bob
Marry
Suzanne
(4 row(s) affected)
Conclusion: Myth Busted!!
You can always restore a database by applying T-LOG backups in sequence, If there are NO gaps in the Log-Chain, irrespective of any intermediate FULL or DIFFRENTIAL backups.
Next Step:
- Go try this yourself
- Recommended read @ SQL BOL: Working with Transaction Log Backups and https://www.sqlskills.com/blogs/paul/post/Debunking-a-couple-of-myths-around-full-database-backups.aspx
* This option is removed from SQL Server 2008 onwards
Hope you'll enjoying demystifying this one along with me.
Varun Dhawan
Support Engineer, Microsoft SQL Server PSS
Reviewed by
Nickson Dicson, Shamik Ghosh
TL, Microsoft SQL Server PSS
Comments
Anonymous
September 04, 2010
Thank you for giving a good explanation but we will get confused by this following statement. -- Restore 3rd T-Log Backup with NORECOVERY RESTORE LOG [SAMPLE_RESTORED] FROM DISK = N'D:BackupSAMPLE_DB-TLog3.trn' WITH FILE = 1, RECOVERY, NOUNLOAD, STATS = 10 GO Which you said NORECOVERY in the top but used RECOVERY. Just FYI. Thank you.Anonymous
September 09, 2010
Hello Sree, Thanks for pointing this out. Yes, In the this step, I trying to restore T-log with RECOVERY. I have made the change accordingly. -- Restore 3rd T-Log Backup with RECOVERY (as this is the last T-Log backup in the chain) RESTORE LOG [SAMPLE_RESTORED] FROM DISK = N'D:BackupSAMPLE_DB-TLog3.trn' WITH FILE = 1, RECOVERY, NOUNLOAD, STATS = 10 GO Appreciate your suggestion. Thanks and regards, Varun Dhawan Support Engineer, Microsoft SQL Server PSSAnonymous
June 27, 2011
Hi, thanks for the post.. I see you're using 'WITH NOFORMAT' option. Would it be the same if I use 'WITH FORMAT' option for all backups?Anonymous
June 30, 2011
The comment has been removedAnonymous
June 30, 2011
Really cool and simple in explanation. Thanks Vasanth Loving SQL forever.Anonymous
February 10, 2012
thx for sharing... i confused when your step 3 : Restore 3rd T-Log Backup with RECOVERY i can used my data but how to restore 4rd T-Log Backup Thank youAnonymous
August 09, 2012
Arkan, As you've noticed, that my LAST T-Log backup is 'SAMPLE_DB-TLog3.trn' and that I haven't taken another T-log backup beyond that. So, during restore operation, If i need to have my data recovered till 'that-specific-point-in-time of last T-log', I need to restore that last in the log chain with RECOVERY option. Does this answers your query. VarunAnonymous
November 15, 2012
Thanks for posting. It is really Very very very nice articleAnonymous
January 17, 2013
nice details has been provided regarding SQL backup soft-engineering.blogspot.comAnonymous
February 19, 2014
The comment has been removedAnonymous
March 07, 2014
The comment has been removedAnonymous
June 29, 2015
Hi Priya Gautam, I Guess you haven't restored your last T-log file with recovery.