{"id":1160,"date":"2007-10-06T01:00:37","date_gmt":"2007-10-06T01:00:37","guid":{"rendered":"\/blogs\/paul\/post\/Search-Engine-QA-6-Using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup.aspx"},"modified":"2007-10-06T01:00:37","modified_gmt":"2007-10-06T01:00:37","slug":"search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/","title":{"rendered":"Search Engine Q&#038;A #6: Using fn_dblog to tell if a transaction is contained in a backup"},"content":{"rendered":"<p><FONT face=Verdana><FONT size=2><br \/>\n<P>Here&#8217;s a really interesting question that was in my search engine logs yesterday&nbsp;&#8211; if I have a transaction that runs and completes while a backup is running, will the complete transaction be in the backup? The answer is&#8230;. it depends!<\/P><br \/>\n<P>In terms of what gets backed up, the way a full backup works is:<\/P><br \/>\n<OL><br \/>\n<LI>Note the transaction log&#8217;s LSN (Log Sequence Number)<br \/>\n<LI>Read all allocated extents in the various data files<br \/>\n<LI>Note the LSN again<br \/>\n<LI>Read all the transaction log between the starting LSN and the ending LSN<\/LI><\/OL><br \/>\n<P>Any transaction that commits before or on the LSN read in step 3 will be fully reflected when the database is restored. If not, the transaction will be undone. So you can&#8217;t just go by the completion time of the backup and the completion time of the transaction. The transaction may well commit before the backup operation completes, but it may complete during step 4, and so it will get rolled back during a restore. In this case, it&#8217;s necessary to take a log backup as well and restore that too to make the transaction be fully reflected after a restore.<\/P><br \/>\n<P>As you know I always like to prove things&nbsp; &#8211; so here&#8217;s my proof of what I just said. I&#8217;m going to use the <FONT face=\"Courier New\">AdventureWorks<\/FONT> database to do this. First thing is to set it to full recovery mode (and take the first full backup to start full recovery mode logging):<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">ALTER<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DATABASE<\/FONT><FONT color=#000000 size=2> AdventureWorks <\/FONT><FONT color=#0000ff size=2>SET<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>RECOVERY<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>FULL<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">BACKUP<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DATABASE<\/FONT><FONT color=#000000 size=2> AdventureWorks <\/FONT><FONT color=#0000ff size=2>TO<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DISK<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#ff0000 size=2>&#8216;C:\\SQLskills\\AdventureWorks.bck&#8217; <\/FONT><FONT color=#0000ff size=2>WITH<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>INIT<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT size=2><br \/>\n<P><FONT face=\"Courier New\">GO<\/FONT><\/P><\/BLOCKQUOTE><br \/>\n<P dir=ltr>Now I&#8217;m going to flush out the backup history tables in MSDB:<\/P><FONT color=#0000ff size=2><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><br \/>\n<P><FONT face=\"Courier New\">USE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> msdb<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">EXEC<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#800000 size=2>sp_delete_backuphistory<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#ff0000 size=2>&#8217;10\/6\/07&#8242;<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT size=2><br \/>\n<P><FONT face=\"Courier New\">GO<\/FONT><\/P><\/BLOCKQUOTE><\/FONT><br \/>\n<P dir=ltr>I&#8217;ve got a really contrived example that I&#8217;m going to use to show whether my transaction is wholely contained in the full backup. Using the <FONT face=\"Courier New\">HumanResources.Employee<\/FONT> table, there&#8217;s a column <FONT face=\"Courier New\">VacationHours<\/FONT> which I&#8217;m going to set to 0 and then force all the changes pages to disk. This is my base state:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">UPDATE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> AdventureWorks<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>HumanResources<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>Employee <\/FONT><FONT color=#0000ff size=2>SET<\/FONT><FONT color=#000000 size=2> VacationHours <\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#000000 size=2> 0<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">CHECKPOINT<\/FONT><\/FONT><FONT color=#808080 size=2><FONT face=\"Courier New\">;<\/FONT><\/P><\/FONT><FONT size=2><br \/>\n<P><FONT face=\"Courier New\">GO<\/FONT><\/P><\/BLOCKQUOTE><br \/>\n<P dir=ltr>My contrived transaction is going to be in a tight loop updating all the rows in the table, which will generate lots of transaction log, and timed to complete just before the backup completes (i.e. in stage 4). In one connection I start the backup:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">BACKUP<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DATABASE<\/FONT><FONT color=#000000 size=2> AdventureWorks <\/FONT><FONT color=#0000ff size=2>TO<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DISK<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#ff0000 size=2>&#8216;C:\\SQLskills\\AdventureWorks.bck&#8217; <\/FONT><FONT color=#0000ff size=2>WITH<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>INIT<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>GETDATE<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#808080 size=2>();<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><\/BLOCKQUOTE><br \/>\n<P dir=ltr>and in another I start my contrived transaction, after starting the backup:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">BEGIN<\/FONT><\/FONT><FONT face=\"Courier New\" color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2><FONT face=\"Courier New\">TRAN<\/FONT><\/P><br \/>\n<P><FONT face=\"Courier New\">DECLARE<\/FONT><\/FONT><FONT face=\"Courier New\" color=#000000 size=2> @a <\/FONT><FONT color=#0000ff size=2><FONT face=\"Courier New\">INT<\/FONT><\/P><br \/>\n<P><FONT face=\"Courier New\">DECLARE<\/FONT><\/FONT><FONT face=\"Courier New\" color=#000000 size=2> @b <\/FONT><FONT color=#0000ff size=2><FONT face=\"Courier New\">INT<\/FONT><\/P><br \/>\n<P><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> @a <\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT size=2><FONT color=#000000> 1<\/FONT><\/P><\/FONT><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">WHILE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#808080 size=2>(<\/FONT><FONT color=#000000 size=2>@a <\/FONT><FONT color=#808080 size=2>&lt;<\/FONT><FONT color=#000000 size=2> 6<\/FONT><FONT color=#808080 size=2>)<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" color=#0000ff size=2><br \/>\n<P>BEGIN<\/P><\/FONT><FONT size=2><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><br \/>\n<P><\/FONT><FONT face=\"Courier New\"><FONT color=#0000ff size=2>SELECT<\/FONT><FONT size=2> @b <\/FONT><FONT color=#808080 size=2>=<\/FONT><\/FONT><FONT size=2><FONT face=\"Courier New\"> 1<\/FONT><\/P><br \/>\n<P><\/FONT><FONT face=\"Courier New\"><FONT color=#0000ff size=2>WHILE<\/FONT><FONT size=2> <\/FONT><FONT color=#808080 size=2>(<\/FONT><FONT size=2>@b <\/FONT><FONT color=#808080 size=2>&lt;<\/FONT><FONT size=2> 201<\/FONT><FONT color=#808080 size=2>)<\/P><\/FONT><\/FONT><FONT size=2><br \/>\n<P><\/FONT><FONT color=#0000ff size=2><FONT face=\"Courier New\">BEGIN<\/FONT><\/P><\/FONT><FONT size=2><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><br \/>\n<P><\/FONT><FONT face=\"Courier New\"><FONT color=#0000ff size=2>UPDATE<\/FONT><FONT size=2> AdventureWorks<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT size=2>HumanResources<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT size=2>Employee <\/FONT><FONT color=#0000ff size=2>SET<\/FONT><FONT size=2> VacationHours <\/FONT><FONT color=#808080 size=2>=<\/FONT><\/FONT><FONT size=2><FONT face=\"Courier New\"> @b<\/FONT><\/P><br \/>\n<P><\/FONT><FONT face=\"Courier New\"><FONT color=#0000ff size=2>SELECT<\/FONT><FONT size=2> @b<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT size=2>@b<\/FONT><FONT color=#808080 size=2>+<\/FONT><\/FONT><FONT size=2><FONT face=\"Courier New\">1<\/FONT><\/P><\/BLOCKQUOTE><br \/>\n<P><\/FONT><FONT color=#0000ff size=2><FONT face=\"Courier New\">END<\/FONT><\/P><\/BLOCKQUOTE><\/FONT><FONT size=2><br \/>\n<P><\/FONT><FONT face=\"Courier New\"><FONT color=#0000ff size=2>SELECT<\/FONT><FONT size=2> @a<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT size=2>@a<\/FONT><FONT color=#808080 size=2>+<\/FONT><FONT size=2>1<\/P><\/FONT><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">END<\/FONT><\/P><br \/>\n<P><FONT face=\"Courier New\">COMMIT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>TRAN<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>GETDATE<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#808080 size=2>();<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><\/BLOCKQUOTE><br \/>\n<P dir=ltr>It&#8217;s not pretty but it does the job. The backup finishes at&nbsp;<FONT color=#008000 size=2><FONT color=#008000 size=2>2007-10-05 17:42:38.983<\/FONT><\/FONT>&nbsp;and the transaction finishes at&nbsp;<FONT color=#008000 size=2><FONT color=#008000 size=2>2007-10-05 17:42:38.107<\/FONT><\/FONT>&nbsp;&#8211; <EM>before<\/EM> the backup finishes. Remember I set the <FONT face=\"Courier New\">VacationHours<\/FONT> all to zero before running my transaction &#8211; let&#8217;s check the transaction did actually change them:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>MAX<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#808080 size=2>(<\/FONT><FONT color=#000000 size=2>VacationHours<\/FONT><FONT color=#808080 size=2>)<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>FROM<\/FONT><FONT color=#000000 size=2> AdventureWorks<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>HumanResources<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>Employee<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT size=2><br \/>\n<P><FONT face=\"Courier New\">GO<\/FONT><\/P><\/BLOCKQUOTE><br \/>\n<P dir=ltr style=\"MARGIN-RIGHT: 0px\"><\/FONT>This returns 200 &#8211; which is what I&#8217;d expect. But is the transaction wholely contained in the backup? Let&#8217;s look at the backup history to find out the last LSN that was captured in the full backup:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> Backup_Start_Date<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT color=#000000 size=2> Backup_Finish_Date<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT color=#000000 size=2> First_LSN<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT size=2><FONT color=#000000> Last_LSN<\/FONT><\/P><\/FONT><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">FROM<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> msdb<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>dbo<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>backupset <\/FONT><FONT color=#0000ff size=2>WHERE<\/FONT><FONT color=#000000 size=2> database_name <\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#ff0000 size=2>&#8216;AdventureWorks&#8217;<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><\/FONT><\/BLOCKQUOTE><br \/>\n<P dir=ltr>And the output we get is:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><br \/>\n<P dir=ltr><FONT face=\"Courier New\">Backup_Start_Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Backup_Finish_Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; First_LSN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Last_LSN<BR>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<BR>2007-10-05 17:42:22.000 2007-10-05 17:42:38.000 86000000001600029&nbsp;&nbsp;&nbsp;91000000625600001<\/FONT><BR><\/P><\/BLOCKQUOTE><br \/>\n<P dir=ltr>The LSNs are in decimal, so we need to convert the three numbers to hex so we can compare them to what&#8217;s in the log &#8211; giving: 5B:1870:1. This is the LSN of the last log record that was backed up in the full backup. Now let&#8217;s take a look at the transaction log for <FONT face=\"Courier New\">AdventureWorks<\/FONT><FONT face=Verdana> using the undocumented <FONT face=\"Courier New\">fn_dblog<\/FONT> function. This is undocumented but very well known. It&#8217;s a fully composable alternative to using the old <FONT face=\"Courier New\">DBCC LOG<\/FONT> command.<\/FONT><\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">USE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> AdventureWorks<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT size=2><br \/>\n<P><FONT face=\"Courier New\">GO<\/FONT><\/P><br \/>\n<P><\/FONT><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> [Current LSN]<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT color=#000000 size=2> Operation<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT color=#000000 size=2> [Transaction ID]<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT size=2><FONT color=#000000> AllocUnitName <\/FONT><\/FONT><FONT color=#0000ff size=2>FROM<\/FONT><FONT color=#000000 size=2> fn_dblog <\/FONT><FONT color=#808080 size=2>(NULL,<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#808080 size=2>NULL);<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><\/BLOCKQUOTE><br \/>\n<P dir=ltr>The log record at that LSN is:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><br \/>\n<P dir=ltr><FONT face=\"Courier New\">00000058:00001870:0001&nbsp; LOP_MODIFY_ROW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0000:00001338&nbsp; HumanResources.Employee.PK_Employee_EmployeeID<\/FONT><BR><\/P><\/BLOCKQUOTE><br \/>\n<P dir=ltr>This is obviously in the middle of my contrived transaction &#8211; showing that it isn&#8217;t all in the full backup. The end of the transaction isn&#8217;t until way later in the log:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><br \/>\n<P dir=ltr><FONT face=\"Courier New\">0000005e:00000628:01b1&nbsp; LOP_MODIFY_ROW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0000:00001338&nbsp; HumanResources.Employee.PK_Employee_EmployeeID<BR>0000005e:00000628:01b2&nbsp; LOP_COMMIT_XACT&nbsp;&nbsp;&nbsp;&nbsp;0000:00001338&nbsp; NULL<\/FONT><BR><\/P><\/BLOCKQUOTE><br \/>\n<P dir=ltr>Before I do anything else, I want to take a log backup to preserve my transaction:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">BACKUP<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>LOG<\/FONT><FONT color=#000000 size=2> AdventureWorks <\/FONT><FONT color=#0000ff size=2>TO<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DISK<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#ff0000 size=2>&#8216;C:\\SQLskills\\AdventureWorks_Log.bck&#8217; <\/FONT><FONT color=#0000ff size=2>WITH<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>INIT<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><\/BLOCKQUOTE><br \/>\n<P dir=ltr>Now I want to restore the full backup and really show that my transaction isn&#8217;t all in there:<\/P><\/FONT><\/FONT><FONT color=#0000ff size=2><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><br \/>\n<P><FONT face=\"Courier New\">USE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>master<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">RESTORE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DATABASE<\/FONT><FONT color=#000000 size=2> AdventureWorks <\/FONT><FONT color=#0000ff size=2>FROM<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DISK<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#ff0000 size=2>&#8216;C:\\SQLskills\\AdventureWorks.bck&#8217; <\/FONT><FONT color=#0000ff size=2>WITH<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>REPLACE<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>RECOVERY<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT size=2><br \/>\n<P><FONT face=\"Courier New\">GO<\/FONT><\/P><\/BLOCKQUOTE><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>MAX<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#808080 size=2>(<\/FONT><FONT color=#000000 size=2>VacationHours<\/FONT><FONT color=#808080 size=2>)<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>FROM<\/FONT><FONT color=#000000 size=2> AdventureWorks<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>HumanResources<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>Employee<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT size=2><br \/>\n<P><FONT face=\"Courier New\">GO<\/FONT><\/P><\/BLOCKQUOTE><br \/>\n<P dir=ltr>This returns 0. Clearly my transaction isn&#8217;t all in there, and the parts that are were rolled back during the restore. Now let&#8217;s do the same thing but using <FONT face=\"Courier New\">NORECOVERY<\/FONT> for the restore of the full backup and also applying the log backup I took:<\/P><br \/>\n<BLOCKQUOTE dir=ltr style=\"MARGIN-RIGHT: 0px\"><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">RESTORE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DATABASE<\/FONT><FONT color=#000000 size=2> AdventureWorks <\/FONT><FONT color=#0000ff size=2>FROM<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DISK<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#ff0000 size=2>&#8216;C:\\SQLskills\\AdventureWorks.bck&#8217; <\/FONT><FONT color=#0000ff size=2>WITH<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>REPLACE<\/FONT><FONT color=#808080 size=2>,<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>NORECOVERY<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">RESTORE<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>LOG<\/FONT><FONT color=#000000 size=2> AdventureWorks <\/FONT><FONT color=#0000ff size=2>FROM<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>DISK<\/FONT><FONT color=#808080 size=2>=<\/FONT><FONT color=#ff0000 size=2>&#8216;C:\\SQLskills\\AdventureWorks_Log.bck&#8217; <\/FONT><FONT color=#0000ff size=2>WITH<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>RECOVERY<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><FONT color=#0000ff size=2><br \/>\n<P><FONT face=\"Courier New\">SELECT<\/FONT><\/FONT><FONT face=\"Courier New\"><FONT color=#000000 size=2> <\/FONT><FONT color=#ff00ff size=2>MAX<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#808080 size=2>(<\/FONT><FONT color=#000000 size=2>VacationHours<\/FONT><FONT color=#808080 size=2>)<\/FONT><FONT color=#000000 size=2> <\/FONT><FONT color=#0000ff size=2>FROM<\/FONT><FONT color=#000000 size=2> AdventureWorks<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>HumanResources<\/FONT><FONT color=#808080 size=2>.<\/FONT><FONT color=#000000 size=2>Employee<\/FONT><FONT color=#808080 size=2>;<\/P><\/FONT><\/FONT><FONT face=\"Courier New\" size=2><br \/>\n<P>GO<\/P><\/FONT><\/BLOCKQUOTE><br \/>\n<P dir=ltr>This time the SELECT returns 200. And now you can start playng around with <FONT face=\"Courier New\">fn_dblog<\/FONT> if you didn&#8217;t know about it before. I&#8217;ll be posting more about&nbsp;Storage Engine&nbsp;internals that you can figure out from the transaction log in future.<\/P><\/FONT><\/FONT><\/FONT><\/FONT><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s a really interesting question that was in my search engine logs yesterday&nbsp;&#8211; if I have a transaction that runs and completes while a backup is running, will the complete transaction be in the backup? The answer is&#8230;. it depends! In terms of what gets backed up, the way a full backup works is: Note [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,38,78,98,100],"tags":[],"class_list":["post-1160","post","type-post","status-publish","format-standard","hentry","category-backuprestore","category-example-scripts","category-search-engine-q-and-a","category-transaction-log","category-undocumented-commands"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Search Engine Q&amp;A #6: Using fn_dblog to tell if a transaction is contained in a backup - Paul S. Randal<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Search Engine Q&amp;A #6: Using fn_dblog to tell if a transaction is contained in a backup - Paul S. Randal\" \/>\n<meta property=\"og:description\" content=\"Here&#8217;s a really interesting question that was in my search engine logs yesterday&nbsp;&#8211; if I have a transaction that runs and completes while a backup is running, will the complete transaction be in the backup? The answer is&#8230;. it depends! In terms of what gets backed up, the way a full backup works is: Note [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/\" \/>\n<meta property=\"og:site_name\" content=\"Paul S. Randal\" \/>\n<meta property=\"article:published_time\" content=\"2007-10-06T01:00:37+00:00\" \/>\n<meta name=\"author\" content=\"Paul Randal\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Paul Randal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/\",\"name\":\"Search Engine Q&A #6: Using fn_dblog to tell if a transaction is contained in a backup - Paul S. Randal\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#website\"},\"datePublished\":\"2007-10-06T01:00:37+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Search Engine Q&#038;A #6: Using fn_dblog to tell if a transaction is contained in a backup\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/\",\"name\":\"Paul S. Randal\",\"description\":\"In Recovery...\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce\",\"name\":\"Paul Randal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g\",\"caption\":\"Paul Randal\"},\"sameAs\":[\"http:\/\/3.209.169.194\/blogs\/paul\"],\"url\":\"https:\/\/www.sqlskills.com\/blogs\/paul\/author\/paul\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Search Engine Q&A #6: Using fn_dblog to tell if a transaction is contained in a backup - Paul S. Randal","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/","og_locale":"en_US","og_type":"article","og_title":"Search Engine Q&A #6: Using fn_dblog to tell if a transaction is contained in a backup - Paul S. Randal","og_description":"Here&#8217;s a really interesting question that was in my search engine logs yesterday&nbsp;&#8211; if I have a transaction that runs and completes while a backup is running, will the complete transaction be in the backup? The answer is&#8230;. it depends! In terms of what gets backed up, the way a full backup works is: Note [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/","og_site_name":"Paul S. Randal","article_published_time":"2007-10-06T01:00:37+00:00","author":"Paul Randal","twitter_misc":{"Written by":"Paul Randal","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/","url":"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/","name":"Search Engine Q&A #6: Using fn_dblog to tell if a transaction is contained in a backup - Paul S. Randal","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#website"},"datePublished":"2007-10-06T01:00:37+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/search-engine-qa-6-using-fn_dblog-to-tell-if-a-transaction-is-contained-in-a-backup\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/paul\/"},{"@type":"ListItem","position":2,"name":"Search Engine Q&#038;A #6: Using fn_dblog to tell if a transaction is contained in a backup"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/paul\/","name":"Paul S. Randal","description":"In Recovery...","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/paul\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/ffcec826c18782e1e0adf173826a7fce","name":"Paul Randal","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/paul\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0b6a266bba2f088f2551ef529293001bd73bf026bc1908b9866728c062beeeb6?s=96&d=mm&r=g","caption":"Paul Randal"},"sameAs":["http:\/\/3.209.169.194\/blogs\/paul"],"url":"https:\/\/www.sqlskills.com\/blogs\/paul\/author\/paul\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/posts\/1160","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/comments?post=1160"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/posts\/1160\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/media?parent=1160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/categories?post=1160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/paul\/wp-json\/wp\/v2\/tags?post=1160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}