深入SQLServer日誌收縮
問題背景
SQLServer的日誌是DB級別的這點和MySQL不同,多個DB就需要維護多個日誌檔案並且每個DB的日誌檔案可以有多個,所以從空間資源的角度來說這給雲上的使用者帶來一些困擾,畢竟在雲上磁碟空間是要收費的,除了效能他們也非常關心這些日誌何時截斷重用、何時收縮
問題探討
在理解事務日誌基本概念的基礎上我們來做個有關收縮的測試:
--1. 構建測試用的日誌
-- tpcc是我的測試DB,ITEM表是之前生成的一個測試表,這裡不需要關心表內容
USE [tpcc]
GO
DECLARE @VALUE INT
SET @VALUE = 0
WHILE @VALUE <= 100
BEGIN
SELECT * INTO ITEM_2 FROM ITEM
DROP TABLE ITEM_2
SET @VALUE = @VALUE + 1
END
GO
--2. 觀察當前等待日誌截斷重用的原因和每個DB的日誌使用量
select log_reuse_wait_desc from sys.databases where name=`tpcc`
go
dbcc sqlperf(logspace)
go
--3. 備份資料和日誌
BACKUP DATABASE TPCC TO DISK=`D:BACKUPTPCC.BAK` WITH COMPRESSION,INIT
BACKUP LOG TPCC TO DISK=`D:BACKUPTPCC.TRN` WITH COMPRESSION,INIT
--4. 再次觀察當前等待日誌截斷重用的原因和每個DB的日誌使用量
select log_reuse_wait_desc from sys.databases where name=`tpcc`
go
dbcc sqlperf(logspace)
go
--5. 收縮日誌
USE [tpcc]
GO
dbcc shrinkfile(log)
--6. 檢視收縮後的日誌使用量
dbcc sqlperf(logspace)
go
這一步也可以通過上一步收縮的結果計算出來(90112*8K = 704 MB);
現在在理解基本概念的基礎上產生了第一個疑問,為什麼1G的日誌使用了4%卻只能收縮到704MB?
為了解答這個問題我們需要引入另一個概念 Virtual Log Files(VLF),SQLServer為了方便日誌管理,邏輯上將事務日誌劃分為多個虛擬日誌檔案,我們要討論的收縮就是以虛擬日誌檔案為單位操作的。
具體可以參考日誌的結構
我們再來重複一次剛才的測試,這次加入對VLFs的記錄觀察;
在剛才的1、3、5步驟之後記錄如下SQL返回結果,幫助後續分析;
USE [tpcc]
GO
dbcc loginfo
步驟1結束後
步驟3結束後
步驟5結束後
這裡跟收縮日誌最相關的是Stats欄位,0表示inactive,2表示active,active狀態的VLF通過checkpoint+日誌備份可以轉化為inactive,但有一個原則是header(可理解為最新的活動日誌)部分只能後推或迴繞(wraps around)不能move forward(跟offset相關);
在開始備份前有11個活動VLF,checkpoint(資料備份的第一階段)+ 備份日誌後只有最新的VLF處於活動狀態(日誌截斷並標記老的VLF為inactive-可重用),收縮後釋放掉了未使用的VLF;
截止到這裡截斷和收縮實際已經達到了充分利用空間的目的,雖然直觀看物理檔案沒有下降多少但新的日誌已經開始迴繞;但即便如此一些客戶還在追求物理檔案的進一步減少,實際想達到這個目的也很簡單,依據之前講的header部分已經迴繞,再次備份收縮就可以了;
--再次備份
backup database tpcc to disk=`d:ackup pcc.bak` with compression,init
backup log tpcc to disk=`d:ackup pcc.trn` with compression,init
--再次收縮
USE [tpcc]
GO
dbcc shrinkfile(log)
--觀察VLF
USE [tpcc]
GO
dbcc loginfo
為什麼沒有收縮最後一個inactive的VLF跟這個DB的日誌初始化大小、shrinkfile的引數有關,簡單說不回收最後一個VLF已經可以達到初始化的大小;
我們也可以通過VLF的總大小和物理檔案對比做一個驗證:
--通過FileSize計算要加8KB的頁頭 67043328+67043328+67043328+67043328+67043328+67043328+67043328+67559424+8192=536870912B=512MB
--通過最後一個偏移量算
469311488+67559424=536870912B=512MB
結論和建議
- 日誌截斷依賴於checkpoint和日誌備份(FULL模式)
- 日誌截斷的含義是把VLF標記為可重用
- 日誌收縮的多少需要看VLF的header和VLF的數量以及大小而不是通過sqlperf返回的結果判斷(這也是很多DBA和使用者誤解的地方)
- VLF的數量是事務日誌建立時初始化好的一個初始值後續會隨日誌增長和增加,大小跟日誌檔案的大小、增長速度相關沒有恆等的計算方法
- 在非雲場景下(傳統使用者),不建議使用者頻繁做日誌收縮去回收空間,因為這種收縮是有很大開銷的,但肯定也不會一直增長,我們通過頻繁的日誌備份做截斷、迴繞日誌檔案以達到節省空間的目的;在雲場景下(RDS),依然也不建議頻繁收縮,但面對一些希望用其它資源換空間資源且業務場景允許的情況下,建議這部分使用者使用OpenAPI定製化自己的備份策略
相關文章
- SQL Server 收縮日誌SQLServer
- SQL語句收縮日誌檔案SQL
- sqlserver收縮資料庫、收縮資料檔案的操作SQLServer資料庫
- sqlserver 資料庫收縮的方法SQLServer資料庫
- SQLServer資料庫日誌太大處理方式SQLServer資料庫
- MySQL 壓縮二進位制日誌MySql
- SQLSERVER 事務日誌的 LSN 到底是什麼?SQLServer
- sqlserver關於日誌傳輸log shipping的總結SQLServer
- SQLSERVER事務日誌已滿 the transaction log for database 'xx' is fullSQLServerDatabase
- SQLServer的頁壓縮SQLServer
- Sqlserver使用遊標迴圈查詢所有sqlserver error日誌帶有Exception的報錯SQLServerErrorException
- SQLServer 2008中事務日誌已滿問題處理SQLServer
- Sqlserver表和索引壓縮SQLServer索引
- 深入理解Logger日誌——框架繫結原理框架
- SQLServer 2012 AG主節點無法截斷事務日誌SQLServer
- [20181112]11g 日誌傳輸壓縮模式.txt模式
- 【譯】深入理解G1的GC日誌(一)GC
- 使用Logstash工具匯入sqlserver資料到elasticSearch及elk分散式日誌中心SQLServerElasticsearch分散式
- 日誌分析-apache日誌分析Apache
- Sqlserver2016啟用了日誌並行,但是實際上某些資料庫日誌並行並沒有生效的問題SQLServer並行資料庫
- [日誌分析篇]-利用ELK分析jumpserver日誌-日誌拆分篇Server
- Kafka-之資料日誌儲存(格式變化與壓縮)Kafka
- 日誌
- 新特性解讀 | MySQL 8.0錯誤日誌深入過濾(上)MySql
- 基於Linux指令碼,對日誌進行定時壓縮備份Linux指令碼
- 資料誤操作,刪庫跑路?教你使用ApexSQLLog工具從 SQLServer日誌恢復資料!SQLServer
- 【Spring】日誌列印sql,日誌配置列印sqlSpringSQL
- [Java/日誌] 日誌框架列印應用程式日誌程式碼的執行情況Java框架
- 日誌列印
- Mysql日誌MySql
- Loggiing日誌
- ros 日誌ROS
- 日誌01
- Log日誌
- 日誌管理
- ELK日誌
- CMS日誌
- 日誌配置
- mybatis日誌MyBatis