為何使用DBCC SHRINKFILE還是無法壓縮資料檔呢?
緣由 : 在某些狀況下我們需要對過肥的LDF檔案進行壓縮作業,來防止因硬碟容量不足導致SQL
服務無法正常。而我們最常用的方式就是利用DBCC SHRINKFILE來針對LDF檔案進行壓縮
(http://msdn.microsoft.com/zh-tw/library/ms189493.aspx)。
然而我們常常會會在執行完DBCC SHRINKFILE後會發現壓縮的效果並不理想,我們明明已經對LDF做了備份,卻還是無法將LDF的容量壓縮到我們的設定值,這是為什麼呢?
首先我們要先了解,雖然我們看到的LDF只是一個檔案,但其實該LDF檔是會分割成很多邏輯片段,一個片段寫完後再寫到下一個片段,我們稱該片段為VLF’s(Virtual Log Files)。有人將LDF形容成是一列火車,而VLF’s就是火車上一節一節的車廂。而我們在ShrinkFile的動作其實就是在移除VLF's
我們設定LDF檔案成長大小也會關聯VLF’s的數量(如下表)
LDF Size |
Number of VLF’s |
1MB < Size < 64MB |
4 |
64MB < Size < 1GB |
8 |
Size > 1GB |
16 |
步驟一 :
1.如下圖所示,我們先建立一個測試資料庫TestDB,LDF一開始為2MB,每次成長則為16MB。
2.建立資料表PrimaryTable_Large,每一筆ROW為1508 Bytes
3.做一次完整備份(如果新建DB沒先做一次完整備份,該DB會以Recovery為simple方式運作)
4.利用DBCC LOGINFO檢視VLF’s狀況。
我們可以看見一開始DB CREATE後產生了4個VLF's檔案,我們可以看一下FileSize欄位,其加總後約略就是我們建立DB時定義的2MB大小。
步驟二 :
1. 我們直接寫入1500筆資料到測試TABLE中(約2.2MB)。
2. 我們由下圖綠色圈選處可以看見LDF依照設定成長了16MB,使用率為18.8%。
3. 我們由下圖紅色圈選處可以看見增加了4個新的VLF’s,每一個VLF約4MB。
4. 我們由下圖藍色圈選處可以看見目前Transaction Log使用了5個的VLF’s(Status欄位狀態為2)。
步驟三 :
1. 我們先做一次交易紀錄備份作業。
2. 我們由下圖綠色圈選處可以看見LDF使用率下降到8.5%。
3. 我們由下圖藍色圈選處可以看見備份後,4個VLF’s 的Status欄位值變更為0,表示該VLF可以Reuse。
4. 我們由下圖紅色圈選處可以看見目前Transaction Log在該VLF上。
我們都知道LDF是循序寫入,這裡可以觀察FSeqNo欄位,就可以了解VLF排序。
步驟四 :
1. 我們用DBCC SHRINKFILE來將LDF檔壓縮到2MB。
2. 由下圖藍色圈選處,我們可以知道目前LDF檔案為6MB左右,使用率為73%左右。
3. 此時VLF's有甚麼變化呢?我們可以看見VLF’s檔案由8個下降為5個。少了3個4MB的VLF。因此我們可以知道壓縮作業就是去刪除VLF's。
4. 由紅色圈選處我們可以發現剛剛的第一筆VLF Status欄位由0變成2了,FSeqNo欄位的值也是目前最大值,表示目前Transaction Log已經Reuse 該VLF了。
步驟五 :
1. 再做一次交易紀錄備份。
2. 我們由下圖紅色圈選處可以看見LDF使用率下降到6.8%。
3. 我們由下圖藍色圈選處可以看見FSeqNo為41的VLF在此次備份後Status也由2變成0了,表示該VLF也可以Reuse。
步驟六 :
1. 經過步驟五再次備份交易紀錄後,我們再做一次DBCC SHRINKFILE(目標2MB)。
2. 由下圖藍色圈選處我們可以發現這一次已經成功的將LDF壓縮到2MB了。
3. VLF's數目也由5個再降到4個。而那4 個VLF's大小總和就是2MB。
結論 : 由這一次實驗我們可以知道DBCC SHRINKFILE就是去移除VLF’s,而我們做完交易紀錄備份後,大多數的VLF's狀態會變更成Reuse,此時該VLF就可以被刪除。而我們常常會發生壓縮下來的空間並不大其原因就是還有VLF無法被刪除,而該VLF卡在中間,導致SHRINK的作業只能刪除到該VLF為止。因此遇見這一種情形您可以稍等一下再做一次交易紀錄備份後,待該VLF檔狀態變成可以Reuse時,再做DBCC SHRINKFILE應該可以有很好的效果了。
我是ROCK
rockchang@mails.fju.edu.tw