探究SQL Server 將交易紀錄寫入Tranaction Log的時間點

  • 2495
  • 0
  • 2014-09-23

探究SQL Server 將交易紀錄寫入Tranaction Log的時間點

緣由 :

某日閱讀書中關於SQL鏡像運作原理時,書中說明Principal在將交易紀錄由Memory中的Buffer寫入到實體的LDF檔時,另一個執行序同時會將交易紀錄傳送給Mirror端,一旦Mirror端也將該交易紀錄寫入自己的LDF檔後才算完成Principal端的整個交易(Mirroring的同步模式)

 

看到上述的文章內容後,我想起百敬老師曾說過交易紀錄在Memory中會保留一塊Cache,所有交易紀錄會先放在該區域然後才寫入LDF實體檔案中。但關於該Cache的大小及寫入的模式,怎麼想都想不起來,好不容易爬到一篇文章就是討論這一方面的內容。參考他的文章後,自己也來實作看看並將過程記錄下來,以免日後又忘了。

 

此次實驗我們會利用Process Monitor來觀察LDF檔被寫入的狀況,大家可以先到http://technet.microsoft.com/zh-tw/sysinternals/bb896645 下載檔案。

 

實驗開始嘍

 

步驟一 : 如下圖我們直接寫入一筆資料到一個資料表中。

clip_image002

 

 

步驟二 : 如下圖,根據Process Monitor擷取到的資料,我們可以看見一筆WriteFile事件寫入到E:\SQLLOG\MyDB_log.ldf檔案中,寫入長度為4096 Byte(4KB)

clip_image004

 

 

步驟三 : 這一次我們直接寫入十筆資料到該資料表中,看看Process Monitor會擷取到哪些資料呢。

clip_image006

 

 

步驟四 : Process Monitor擷取到10WriteFile事件寫入到E:\SQLLOG\MyDB_log.ldf檔案中,每一筆寫入長度都是4096 Byte(4KB)

clip_image008

 

步驟五 : 這一次我們故意將Insert的動作包到交易中,且故意不Commit

clip_image010

步驟六 : 針對沒有Commit的那一筆交易,我們可以發現LDF並沒有被寫入的紀錄。

clip_image012

 

步驟七: 此時我們回去將剛剛那一筆交易Commit掉。

clip_image014

 

 

步驟八: 會發現Commit掉後的交易被寫入LDF檔了。

clip_image016

 

 

小結 :

        由上述八個步驟我們可以瞭解,只要是Commit的交易都會被寫入到LDF檔中。

 

 

 

 

 

 

 

 

步驟九 : 剛剛我們都只是針對單筆交易觀察,接下來對於批次交易,SQL又是如何處理Tranaction Log的寫入呢,如下圖所示,我們在一筆交易中寫入600筆資料。

clip_image018

 

 

 

 

步驟十 : 如下圖所示Process Monitor只擷取到2筆寫入LDF動作,第一筆寫了61440 Byte(60KB),而第二筆寫入16384 Bytes(16KB),所以我們大概可以知道該Cache的大小應該就是60KB,一旦到達60KB就算交易還沒結束,SQL也會強制將Cache中所有交易紀錄寫入到LDF中。

clip_image020

 

 

 

 

 

 

 

 

步驟十一 : 這一次我們故意將剛剛步驟九的那個長交易不Commit掉,此時應該只會有一筆寫入動作(因為Cache滿了而被強制寫入的那60KB),來看看我們的推測是否正確吧。

clip_image022

 

步驟十二 : 沒錯 ! 如下圖所示,果然只有一筆60KB的寫入紀錄。

clip_image024

 

 

步驟十三 : 回去Commit掉剛剛的交易吧。

clip_image026

步驟十四 : 我們在步驟十三Commit掉長交易後,又多了一筆16KB被寫入LDF檔了。

clip_image028

 

小結 :

        由上述步驟九到步驟十四實驗,我們可以知道該Cache的容量大小為60KB一旦Cache滿了,即使交易尚未結束,SQL也會將Cache中的資料寫入LDF

 

 

 

 

 

 

 

步驟十五 : 此時我突然想到,萬一還有交易紀錄是在Cache中尚未寫進LDF,此時發生Checkpoint事件,所有Dirty Page都被寫入MDF檔,然後SQL Server突然Crush掉。那會不會因為還有尚未寫入LDF的交易紀錄遺失,導致SQL無法利用LDF正確的Undo交易回來呢 ?

        因此我繼續利用剛剛的長交易且故意不Commit交易,讓Cache中殘存本次交易中的部分交易紀錄。

clip_image030

步驟十六 : 步驟十五Commit的長交易因為60KBCache滿了,所以有一筆60KB寫入LDF的紀錄,但根據剛剛的實驗我們知道本交易應該還有16KB的交易紀錄還存放在Cache中尚未寫入LDF案內。

clip_image032

 

 

步驟十七 : 我們開另一條Session執行Checkpoint動作看看Process Monitor會擷取到哪些資料呢。

clip_image034

 

 

步驟十八 : 如下圖紅色圈選處,我們可以發現當Checkpoint事件發生時,Cache中的所有交易紀錄也會被寫入到LDF檔案中,即便那些交易還沒有Commit掉。且多了四筆紀錄Checkpoint的事件寫入。

clip_image036

小結 :

        Checkpoint事件發生時,即使交易尚未結束,SQL也會將Cache中的資料寫入LDF

 

 

步驟十九 : SQL2014有新增一個叫做Delayed Durability的功能,其目的就是降低Cache寫入到LDFIO數,大量的IO會影響到SQL的效能。我們可以從步驟一到八的實驗中知道,當我們不是用批次的方式寫入資料到資料表中。而是用大量的單筆交易來塞入資料,那每一筆資料完成交易就會IO一次LDF檔,這是很耗效能的。而Delayed Durability的功能就是要降低LDF檔的IO數,會累積一定的交易紀錄後在一次寫入到LDF檔中來加快速度。當然這樣的做法就是會增加資料不一致的風險嘍。

        下圖中我們開啟DBDelayed Durability功能。

clip_image038

 

 

 

 

步驟二十 : 用單筆交易的方式寫入10筆資料到資料表中,我們可以從步驟四看見在尚未開啟Delayed Durability功能時,會有104KLDF寫入動作。

clip_image040

 

 

 

步驟二十一 : 用單筆交易的方式寫入10筆資料到資料表中,在開啟Delayed Durability功能後,Process Monitor只擷取到一次的IO(如下圖)

clip_image042

 

 

 

 

總結 :

1.      Cache的容量大小為60KB

2.      只要是Commit的交易都會被寫入到LDF檔案中。

3.      一旦Cache滿了,即使交易尚未結束,SQL也會將Cache中的資料寫入LDF檔案中。

4.      Checkpoint事件發生時,即使交易尚未結束,SQL也會將Cache中的資料寫入LDF檔案中

5.      開啟Delayed Durability功能後,SQL降低LDF檔案的IO數來增加效能,但會增加資料不一致的風險。

 

 

 

參考資料來源 :

Observing SQL Server Transaction Log Flush Sizes using Extended Events and Process Monitor

Control Transaction Durability

 

 

 

 

ROCK

2014/9/21

 

 

 

 

我是ROCK

rockchang@mails.fju.edu.tw