[SQL SERVER][Maintain]管理交易記錄檔(1)

[SQL SERVER][Maintain]管理交易記錄檔(1)


交易記錄檔暴增問題是我常常看到的問題,

大多數情況交易記錄檔大小往往都是資料庫大小數十倍以上,

如果DBA放任不管理交易記錄檔的話,

過大的交易記錄檔會影響DB Mirroring、Log Shipping、CDC、Replication、備份效能...等,

嚴重將導致資料庫成為唯讀狀態(硬碟空間被吃爆,SQL Server拋出9002錯誤),

所以管理交易記錄檔可說是相當重要。



論壇網友詢問在做Tables大量寫入,更新,計算,刪除時希望log不會變很大?

因為我大多數的case都不允許我更改資料庫復原模式,

所以我這裡簡單測試在完整復原模式下的方法。




建立交易記錄檔初始大小=60MB 成長量=10MB,RecoveryMode=Full

建立來源資料表(新增40萬筆後交易記錄檔使用量)


SELECT instance_name AS DatabaseName, 
       [Data File(s) Size (KB)], 
       [LOG File(s) Size (KB)], 
       [Log File(s) Used Size (KB)], 
       [Percent Log Used] 
FROM 
( 
   SELECT * 
   FROM sys.dm_os_performance_counters 
   WHERE counter_name IN 
   ( 
       'Data File(s) Size (KB)', 
       'Log File(s) Size (KB)', 
       'Log File(s) Used Size (KB)', 
       'Percent Log Used' 
   ) 
     AND instance_name != '_Total' 
) AS Src 
PIVOT 
( 
   MAX(cntr_value) 
   FOR counter_name IN 
   ( 
       [Data File(s) Size (KB)], 
       [LOG File(s) Size (KB)], 
       [Log File(s) Used Size (KB)], 
       [Percent Log Used] 
   ) 
) AS pvt 
WHERE instance_name='demo' 

 

image

建立來源資料表並匯入資料,交易記錄檔使用16999(KB)27%。

 

 

接下來模擬網友資料操作過程

 

Create


CREATE TABLE [dbo].[MyLOG1](
    [LogId] [int] identity(1,1) NOT NULL,
    agentname varchar(30) not null,
    [LogDate] [datetime] NOT NULL,    
    constraint PK_MyLOG1 primary key(LogId)
) ON [PRIMARY]

 

image

 

 

Add Column


ALTER table dbo.MyLOG1 add new1 char(1) null

image 

 

 

Move Data(移動300000筆)


INSERT INTO MyLOG1 (agentname,LogDate)
SELECT agentname,LogDate FROM sourceLog 
where [LogId]>0 AND [LogId]<=300000

image 

總共使用36191 KB,最後交易記錄檔大小53190KB。

 

由於邏輯交易記錄檔結尾已達實體記錄檔結尾,

且沒有執行交易記錄檔備份(沒有截斷並標示之前空間重用),

所以發生實體交易記錄檔自動擴充行為(新增VLF)。

 

 

註:


VLF數量沒有固定。

VLF大小沒有固定。

VLF會從實體記錄檔最前面開始依順序寫入紀錄。

 

接下來執行備份資料庫和交易記錄檔後,看看備份檔案大小。

image

image

 

 

避免長時間交易(減少資料量)和uncommitted 交易

上面我們知道資料操作會產生大量的交易記錄,

所以下面針對資料操作我將使用迴圈來處理,

將每一批次資料量縮小(藉以縮短交易時間),

並和大交易資料量所產生的交易記錄大小做個比較,

照理說短時間交易會產生較小的交易記錄量。

 

 

刪除資料庫並重新建立資料庫和來源資料表,

這次針對資料操作改成迴圈處理大資料量(同樣30萬筆)。


DECLARE @batchcount int,@startcount int
set @batchcount=2000
set @startcount=0
BEGIN try
    WHILE(@batchcount<=300000)
    begin        
        INSERT INTO MyLOG2 (agentname,LogDate)
        SELECT agentname,LogDate FROM SourceLOG 
        where [LogId]>@startcount AND [LogId]<=@batchcount        
        set @startcount= @batchcount
        set @batchcount=@batchcount+2000          
    end
end try
begin catch
 print error_message();
end catch

 

image

總共多了20780 KB,最後交易記錄檔大小37788KB。

 

和第一次大交易資料量整整少了快20MB的交易記錄檔大小,

拆解小交易資料量果然使用較少交易記錄量,

同時也沒有發生交易記錄檔擴充處理,

這是因為SQL Server不需要額外過多的交易記錄檔空間來存放rollback操作記錄,

這是要確保可以正常完成rollback作業,

所以縮短交易時間可以達到減少交易記錄檔大小也是很合理的。

 

 

接下來執行備份資料庫和交易記錄檔後,並和之前備份檔案比較一下。

image

image

 

 

善用Partition Table

針對資料新增、刪除作業是否還有其他方法來減少交易記錄檔大小呢?

答案當然是有的,你可以參考我之前的Partition Table來處理,

因為switch partition方法只有紀錄metadata(最小記錄)。

[SQL SERVER][Performance]善用Partition Table#2測試

 

 

結論

交易記錄檔的暴增,都是因為長時間(龐大)交易活動所造成,

例如龐大的資料新增、刪除、更新或索引重建維護作業,

如果這些作業可以在簡單或大量紀錄復原模式下操作的話,

基本上可以減少交易記錄檔成長的大小(因為這兩種模式只記錄最小操作過程記錄),

但我遇到大多數正示環境資料庫都不太允許更改復原模式(會有資料遺失風險-SLAs and OLAs),

所以往往這些龐大作業幾乎都得在完整復原模式下執行,

這時交易記錄檔初始大小、成長大小和交易記錄檔備份頻率規畫就相當重要了,

當然還是要避免長時間交易,因為這不管資料庫是什麼樣的復原模式。

 

 

注意:

大多數人認為執行資料庫完整備份就會自動截斷交易記錄檔並保護data file and log file內容,

但事實上並不會截斷交易記錄檔,而且只有保護data file 內容並不保護log file 內容,

只要沒有執行備份交易記錄檔,交易記錄檔空間不會被截斷並標示重用,

且交易記錄檔將持續成長(直到硬碟空間滿),這裡特別提醒一下。

 

 

 

參考

sys.databases (Transact-SQL)

DBCC SQLPERF (Transact-SQL)

交易記錄檔實體架構

檢查點與記錄檔的使用中部份

交易記錄截斷