SQL 2014新特性- Delayed durability

stswordman發表於2014-06-12

ACID 是資料庫的基本屬性。其中的D是指"永續性":只要事務已經提交,對應的資料修改就會被儲存下來,即使出現斷電等情況,當系統重啟後之前已經提交的資料依然能夠反映到資料庫中。

   

那麼D特性是如何在SQL Server中實現的呢?SQL Server使用write-ahead logging的方式,保證日誌記錄會先於資料記錄固化到磁碟中。當事務提交後,只有當日志記錄固化到磁碟時,才會向客戶端返回提交成功的訊息,至於相應的資料記錄,會透過非同步的方式後續寫入到磁碟中。如果在此期間發生斷電等故障,那麼就會出現以下兩種情況:

  1. 日誌已經寫入到磁碟(committed),但資料沒有寫入:

    系統重啟後進行redo操作,透過讀取日誌,來將沒有固化到資料檔案的資訊寫入到資料檔案。

  2. 部分日誌已經寫入到磁碟(uncommitted),資料部分寫入或沒有寫入

    系統重啟後執行undo操作,將沒有提交的事務對應的資料從資料檔案中清除。

   

這樣就保證了已經提交的事務不會丟失。

   

Delayed durability

SQL Server 2014中引入了一個新的特性,叫做Delayed durability(也稱作lazy commit),顛覆了之前提到的概念。透過Delayed durability,可以讓日誌記錄按照一定規律非同步地寫入到日誌檔案中,避免日誌磁碟寫入過於頻繁。這樣就以犧牲Durability來換取效能

   

應用場景:

使用該特性的前提是您的應用可以容忍一定程度的資料丟失。

日誌磁碟出現系統瓶頸。

由於日誌磁碟效能問題,導致事務無法提交,導致相應的資源(memory,lock等)無法釋放引發的資源競爭

   

Delayed Durability有以下特性:

  1. 一旦事務提交,事務中的資料變更對其他事務(包含full durable transactiondelayed durability transaction)可見。具體請參考isolation level http://msdn.microsoft.com/en-us/library/dn133175.aspx
  2. 事務的永續性(durability)依賴於日誌記錄是否固化到磁碟。
  3. 記憶體中的日誌記錄只有在任意以下情況發生時才會固化到磁碟:
    1. )Full durable transaction進行了資料變更,並且commit.
    2. )執行了sp_flush_log儲存過程.
    3. )Log buffer滿了,日誌記錄也會固化到磁碟.

如果1)2)出現兩次,那麼SQLSERVER會保證第一次之前的Delayed durability transaction的資料變更已經被固化到了磁碟。

   

如何使用Delayed durability

Delayed durability是一個資料庫級別的特性,預設是禁用的,我們首先要開啟這個選項。

ALTER DATABASE [DDtest] SET DELAYED_DURABILITY = FORCED|Allowed|Disabled

   

如果是forced,那麼該資料庫內所有的事務都強制使用delayed durability;如果是allowed,那麼delayed durabilityfull durable transaction可以同時存在;如果是disabled,那麼無法使用delayed durability.

   

   

當該屬性發生變化後,errorlog中也會有相應的記錄

Setting database option delayed_durability to forced for database 'DDtest'.

Setting database option delayed_durability to allowed for database 'DDtest'.

Setting database option delayed_durability to disabled for database 'DDtest'.

   

   

如果資料庫的DELAYED_DURABILITYAllowed,我們可以在語句級別進行控制,否則就要遵循資料庫的設定了(如果語句的設定和資料庫級別設定衝突,那麼SQL Server會使用資料庫級別的設定)。

   

事例

將資料的 DELAYED_DURABILITY設定為Allowed

ALTER DATABASE [DDtest] SET DELAYED_DURABILITY = Allowed

   

建立一張表,並迴圈插入1000行資料,每次插入都是一個單獨的事務

create table ta(col int)

 

declare @N int=0

while @n<1000

begin

begin tran

insert ta values(1)

commit tran with(delayed_durability=off)

set @N+=1

print cast(@N as varchar(1000))

end

   

開啟Process Monitor,監控對資料庫日誌檔案的操作。

一共對日誌檔案進行了1012次的寫入操作,也就是每次commit都會立刻固化到日誌檔案

   

   

下面比較一下使用delayed durability的情況

declare @N int=0

while @n<1000

begin

begin tran

insert ta values(1)

commit tran with(delayed_durability=on)

set @N+=1

print cast(@N as varchar(1000))

end

1000個事務只觸發了32次寫入,大大地減少了對日誌檔案的寫入操作。

   

   

注意事項

  1. 當系統不忙時,也會主動將delayed durability的日誌記錄固化到磁碟。但目前不知道如何判斷"不忙"這個標準。
  2. checkpoint不會將delayed durability的日誌記錄固化到磁碟。
  3. SQL Server正常關閉不會將delayed durability的日誌記錄固化到磁碟,也就說正常關閉也可能會導致資料丟失,建議之前先執行sp_flush_log

相關文章