天天看點

SQL Server 為什麼事務日志自動增長會降低你的性能

  在這篇文章裡,我想詳細談下為什麼你要避免事務日志(transaction log)上的自動增長操作(auto growth operations)。很多運作的資料庫伺服器,對于事務日志,用的都是預設的日志檔案大小和自動增長設定。人們有時會很依賴自動增長機制,因為它們剛好能正常工作。當然,如果它正常工作的話,你不必太關注它,但很快你會發現會有問題出現。

  隻依賴于事務日志的自動增長機制總不是個好主意。首先它會導緻嚴重的日志碎片(log fragmentation),在sql server啟動期間,在你資料庫上執行崩潰恢複(crash recovery)時會有很大的負面影響。另外,在你資料庫裡寫入事務需要等待,隻要事務日志觸發了自動增長機制。

  當事務日志的自動增長機制發生時,sql server總要零初始化新塊,這個會在檔案末尾加上。這和你的sql server執行個體是否用即時檔案初始化(instant file initialization)特權——事務日志總會零初始化。這上面的原因非常明顯:當sql server在過去已經完成事務日志的環繞式處理(wrap-around ),崩潰恢複(crash recovery)需要知道在哪裡停。

  零初始化的問題是會占用更多的時間(取決與你的自動增長率,還有你的存儲速度)。在此期間沒有别的事務可以寫事務日志記錄到事務日志。在事務日志管理器上會有闩鎖造成的阻塞。是以你的寫入事務會進入挂起狀态(直到它們獲得需要的闩鎖),它們就等啊,等啊,等啊,直到你的事務日志自動增長完成。讓我們用一個簡單的例子示範下。

  首先我為這個示範建立一個新的資料庫。對于這個資料庫,這裡我不用預設的設定,對于事務日志,我指定了10gb的自動增長系數。這個的确是個不好的做法,但我隻是用它來展示這個設定的副作用。請不要在你的生産資料庫裡使用這個錯誤配置!!! 

SQL Server 為什麼事務日志自動增長會降低你的性能
SQL Server 為什麼事務日志自動增長會降低你的性能

  下一步裡我在資料庫裡建立2個表。第1個表我通過插入一些日志來快速填充我的事務日志。在事務日志自動增長階段,我們在第2個表裡插入新的記錄來證明這個事務會被自動增長機制阻塞。

SQL Server 為什麼事務日志自動增長會降低你的性能
SQL Server 為什麼事務日志自動增長會降低你的性能

  現在我們已經建立了必須的資料庫對象,因次我可以通過新的沒有立即送出的事務來填充事務日志:

  因為我們現在有了進行中,沒送出的事務,sql server不能重用那部分事務日志,即這個事務存儲的事務日志。它們有需要復原的可能。是以現在我通過不同的會話插入66條其他記錄來填充事務日志:

  最後在第一個會話裡送出我們的事務:

  這意味着在我們面前有一個幾乎滿的的事務日志,我們可以通過dbcc loginfo來驗證:

SQL Server 為什麼事務日志自動增長會降低你的性能

  現在當我們往表裡插入兮的記錄時,事務日志已經沒有可用空間了,sql server進入事務日志的自動增長。

  在自動增長期間的同時,為了監控發生了什麼,我們可以在ssms裡打開新的一個會話視窗,嘗試在第2個表插入另外的記錄——表foo:

  這個sql 語句會阻塞,因為事務要寫入事務日志記錄的事務日志,目前不可用。為了進一步分析這個阻塞情形,你可以打開第3個會話視窗,執行下列2個sql語句:

SQL Server 為什麼事務日志自動增長會降低你的性能
SQL Server 為什麼事務日志自動增長會降低你的性能

(額,俺本機測試失敗………………)

  insert語句嘗試在foo表裡插入新的記錄出現latch_ex等待類型。如你從dmv sys.dm_os_waiting_tasks 裡的resource_description列所見,在sql server的日志管理器上需要獲得闩鎖。你可以通過查詢dmv sys.dm_os_latch_stats 限制lactch class為log_manager再次确認。在那個特定闩鎖上你會看到一些等待。那個闩鎖是事務擷取的,由事務日志的自動增長觸發,隻要這個闩鎖要獲得,每個其他寫事務都會被阻塞。是以在系統上有大量等待時間時,這暗示這在事務日志裡目前有自動增長問題需要處理。

  感謝關注!