SQL Server日誌的自我陳述--數據庫日誌介紹和管理不完全指南

SQL Server日誌的自我陳述--數據庫日誌介紹和管理不完全指南

作者:Max Shen

聽過了人間的悲喜,最難過的莫過於做IT的數據庫壞掉了。而更難過的是沒有備份,比更難過還難過的是日誌不完整。

是時候講一講日誌的故事。不懂日誌的DBA一定是個一個假的DBA,不懂日誌備份的工程師一定沒經歷過系統的大悲大喜。

關鍵知識點

每個  SQL Server 數據庫都具有事務日誌,用於記錄所有事務以及每個事務對數據庫所做的修改。 事務日誌是數據庫的重要組件,如果系統出現故障,則可能需要使用事務日誌將數據庫恢復到一致狀態。

很多工程師對於數據庫日誌總覺得沒有用,甚至不保留日誌, 對於這樣的工程師來說,只能說上帝保佑你吧。

SQL Server 事務日誌按邏輯運行,就好像事務日誌是一串日誌記錄一樣。 每條日誌記錄由一個日誌序列號 (LSN) 標識。 每條新日誌記錄均寫入日誌的邏輯結尾處,並使用一個比前面記錄的 LSN 更高的 LSN。 日誌記錄按創建時的串行序列存儲。 每條日誌記錄都包含其所屬事務的 ID。 對於每個事務,與事務相關聯的所有日誌記錄通過使用可提高事務回滾速度的向後指針挨個鏈接在一個鏈中。  

日誌包含操作

許多類型的操作都記錄在事務日誌中。 這些操作包括:  

  • 每個事務的開始和結束。 

  • 每次數據修改(插入、更新或刪除)。 這包括系統存儲過程或數據定義語言 (DDL) 語句對包括系統表在內的任何表所做的更改。 

  • 每次分配或釋放區和頁。 

  • 創建或刪除表或索引。 

    回滾操作也記錄在日誌中。 每個事務都在事務日誌中保留空間,以確保存在足夠的日誌空間來支持由顯式回滾語句或遇到錯誤引起的回滾。 保留的空間量取決於在事務中執行的操作,但通常等於用於記錄每個操作的空間量。 事務完成後將釋放此保留空間。 

    在很多時候發現數據沒有響應,有沒有任何的用戶操作,但是數據庫處理工作狀態,包括進行分離後附加也有不行,這樣的情況可能就是日誌在進行回滾,做了什麼大型的操作導致,所以在數據庫運維的一條規則,建議對數據庫的大數據集操作進行分片化

日誌物理體系結構

數據庫中的事務日誌映射在一個或多個物理文件上。 從概念上講,日誌文件是一系列日誌記錄。 從物理上講,日誌記錄序列被有效地存儲在實現事務日誌的物理文件集中。 每個數據庫必須至少有一個日誌文件。  

SQL Server 數據庫引擎 在內部將每物理日誌文件分成多個虛擬日誌文件 (VLF)。 虛擬日誌文件沒有固定大小,且物理日誌文件所包含的虛擬日誌文件數不固定。 數據庫引擎 在創建或擴展日誌文件時動態選擇虛擬日誌文件的大小。 數據庫引擎 嘗試維護少量的虛擬文件。 在擴展日誌文件後,虛擬文件的大小是現有日誌大小和新文件增量大小之和。 管理員不能配置或設置虛擬日誌文件的大小或數量。

虛擬日誌文件 (VLF) 的創建遵循此方法:

  • 如果下一次增長少於當前日誌物理大小的 1/8,則創建 1 個 VLF,補償此增長大小(從  SQL Server 2014 (12.x) 開始)

  • 如果下一次增長超過當前日誌大小的 1/8,則使用 pre-2014 方法:

    • 如果增長少於 64 MB,創建 4 個 VLF,補償此增長大小(如增長 1 MB,創建四個 256KB 的 VLF)

    • 如果增長在 64 MB 到 1GB 之間,創建 8 個 VLF,補償此增長大小(如增長 512 MB,創建八個 64MB 的 VLF)

    • 如果增長大於 1GB,創建 16 個 VLF,補償此增長大小(如增長 8 GB,創建十六個 512MB VLF)

如果這些日誌文件由於許多微小增量而增長到很大,則它們將具有很多虛擬日誌文件。 這會降低數據庫啓動以及日誌備份和還原操作的速度。 相反,如果日誌文件設置得較大,但只有少量或僅一個增量,則它們將只有幾個非常大的虛擬日誌文件。

建議爲日誌文件分配一個接近於最終所需大小的 size 值,使用所需增量實現最佳 VLF 分發,並且還要分配一個相對較大的 自動增長值。 

工作機制

事務日誌是一種迴繞的文件。 例如,假設有一個數據庫,它包含一個分成四個 VLF 的物理日誌文件。 當創建數據庫時,邏輯日誌文件從物理日誌文件的始端開始。 新日誌記錄被添加到邏輯日誌的末端,然後向物理日誌的末端擴張。 日誌截斷將釋放記錄全部在最小恢復日誌序列號 (MinLSN) 之前出現的所有虛擬日誌。 MinLSN 是成功進行數據庫範圍內回滾所需的最早日誌記錄的日誌序列號。 如下圖所示相似。


當邏輯日誌的末端到達物理日誌文件的末端時,新的日誌記錄將回繞到物理日誌文件的始端。



這個循環不斷重複,只要邏輯日誌的末端不到達邏輯日誌的始端。 如果經常截斷舊的日誌記錄,始終爲到下一個檢查點前創建的所有新日誌記錄保留足夠的空間,則日誌永遠不會填滿。 但是,如果邏輯日誌的末端真的到達了邏輯日誌的始端,將發生以下兩種情況之一: 

如果對日誌啓用了 FILEGROWTH 設置且磁盤上有可用空間,則文件就按 growth_increment 參數指定的數量增大,並且新的日誌記錄將添加到增大的空間中。

  • 如果未啓用 FILEGROWTH 設置,或保存日誌文件的磁盤的可用空間比 growth_increment 中指定的數量少,則會出現 9002 錯誤。

    如果日誌包含多個物理日誌文件,則邏輯日誌在迴繞到首個物理日誌文件始端之前,將沿着所有物理日誌文件移動。

活動日誌

日誌文件中從必須存在以確保數據庫範圍內成功回滾的第一條日誌記錄到最後寫入的日誌記錄之間的部分稱爲日誌的活動部分,即“活動日誌”。 這是進行數據庫完整恢復所需的日誌部分。

永遠不能截斷活動日誌的任何部分。這就是很多人說日誌不能截斷的原因。

此第一條日誌記錄的日誌序列號 (LSN),稱爲最小恢復 LSN (MinLSN)。

日誌文件中從 MinLSN 到最後寫入的日誌記錄這一部分稱爲日誌的活動部分,或者稱爲活動日誌。 這是進行數據庫完整恢復所需的日誌部分。 永遠不能截斷活動日誌的任何部分。 所有的日誌記錄都必須從 MinLSN 之前的日誌部分截斷。

下圖顯示了具有兩個活動事務的結束事務日誌的簡化版本。 檢查點記錄已壓縮成單個記錄。

LSN 148 是事務日誌中的最後一條記錄。 在處理 LSN 147 處記錄的檢查點時,Tran 1 已經提交,而 Tran 2 是唯一的活動事務。 這就使 Tran 2 的第一條日誌記錄成爲執行最後一個檢查點時處於活動狀態的事務的最舊日誌記錄。 這使 LSN 142(Tran 2 的開始事務記錄)成爲 MinLSN。

活動日誌必須包括所有未提交事務的每一部分。 如果應用程序開始執行一個事務但未提交或回滾,將會阻止數據庫引擎推進 MinLSN。 這可能會導致兩種問題:

  • 如果系統在事務執行了許多未提交的修改後關閉,以後重新啓動時,恢復階段所用的時間將比“恢復間隔”選項指定的時間長得多。

  • 因爲不能截斷 MinLSN 之後的日誌部分,日誌可能變得很大。 即使數據庫使用的是簡單恢復模式,這種情況也有可能出現,在簡單恢復模式下,每次執行自動檢查點操作時通常都會截斷事務日誌。

複製事務

日誌讀取器代理監視已爲事務複製配置的每個數據庫的事務日誌,並將已設複製標記的事務從事務日誌複製到分發數據庫中。 活動日誌必須包含標記爲要複製但尚未傳遞給分發數據庫的所有事務。 如果不及時複製這些事務,它們可能會阻止截斷日誌

數據庫檢查點

檢查點將髒數據頁從當前數據庫的緩衝區高速緩存刷新到磁盤上。 這最大限度地減少了數據庫完整恢復時必須處理的活動日誌部分。 在完整恢復時,需執行下列操作:

  • 前滾系統停止之前尚未刷新到磁盤上的日誌記錄修改信息。

  • 回滾與未完成的事務(如沒有 COMMIT 或 ROLLBACK 日誌記錄的事務)相關聯的所有修改。

    檢查點的操作

    檢查點在數據庫中執行下列過程:

    • 將記錄寫入標記檢查點起點的日誌文件。

    • 將爲檢查點記錄的信息存儲在檢查點日誌記錄鏈內。 

        檢查點中記錄的一條信息是第一條日誌記錄的日誌序列號 (LSN),該 LSN 必須存在才能進行成功的數據庫範圍的回滾。 該 LSN 稱爲“最小恢復 LSN”(“MinLSN”)。 MinLSN 是下列各項中的最小者:

      • 檢查點起點的 LSN。

      • 最早的活動事務起點的 LSN。

      • 尚未傳遞給分發數據庫的最早的複製事務起點的 LSN。

        檢查點記錄還包含所有已修改數據庫的活動事務的列表。

    • 如果數據庫使用簡單恢復模式,則標記在 MinLSN 前重用的空間。

    • 將所有髒日誌和數據頁寫入磁盤。

    • 將標記檢查點結束的記錄寫入日誌文件。

    • 將這條鏈起點的 LSN 寫入數據庫引導頁。

下列情況下將出現檢查點:

  • 顯式執行 CHECKPOINT 語句。 用於連接的當前數據庫中出現檢查點。

  • 在數據庫中執行了最小日誌記錄操作,例如,在使用大容量日誌恢復模式的數據庫中執行大容量複製操作。

  • 已經使用 ALTER DATABASE 添加或刪除了數據庫文件。

  • 通過 SHUTDOWN 語句或通過停止 SQL Server (MSSQLSERVER) 服務停止了 SQL Server 實例。 任一操作都會在 SQL Server 實例的每個數據庫中生成一個檢查點。

  • SQL Server 實例在每個數據庫內定期生成自動檢查點,以減少實例恢復數據庫所需的時間。

  • 進行了數據庫備份。

  • 執行了需要關閉數據庫的活動。 例如,AUTO_CLOSE 設置爲 ON 並且關閉了數據庫的最後一個用戶連接,或者執行了需要重新啓動數據庫的數據庫選項更改。

自動檢查點

SQL Server 數據庫引擎生成自動檢查點。 自動檢查點之間的間隔基於使用的日誌空間量以及自上一個檢查點以來經歷的時間。 如果只在數據庫中進行了很少的修改,自動檢查點之間的時間間隔可能變化很大並且很長。 如果修改了大量數據,自動檢查點也會經常出現。

使用“恢復間隔”服務器配置選項爲服務器實例上的所有數據庫計算自動檢查點之間的間隔。 此選項指定數據庫引擎在系統重新啓動時恢復數據庫所用的最長時間。 數據庫引擎將估計在執行恢復操作期間自己在“恢復間隔”內能夠處理多少條日誌記錄。 

自動檢查點之間的間隔也取決於恢復模式:

  • 如果數據庫使用的是完整恢復模式或批量日誌恢復模式,則每當日誌記錄數達到數據庫引擎估計在“恢復間隔”選項中指定的時間內可以處理的數量時,便會生成一個自動檢查點。

  • 如果數據庫使用的是簡單恢復模式,只要日誌記錄數達到下面兩個值中較小的那個值,就會生成自動檢查點:

    • 日誌已滿 70%。

    • 日誌記錄數達到數據庫引擎估計在“恢復間隔”選項指定的時間內能夠處理的記錄數。


    • 說了 這麼多其實檢查點不用管,基本上1分鐘會自己做一次

最佳實踐

控制日誌大小

日誌的變化會非常影響系統,曾經碰到過客戶數據文件只有5G,日誌文件超過300G,這是絕對不正常的。 因此我們需要對日誌進行監控,管理,控制,其中重要的就是控制日誌大小。

監控日誌

使用 select * from sys.dm_db_log_space_usage  可以查看到日誌空間情況。

select * from sys.database_files  可以看到日誌的配置情況。

管理tempdb日誌

tempdb 如果過大,最好的處理方式是 :重新啓動服務器實例可以將 tempdb 數據庫的事務日誌調整到自動增長之前的原始大小。但是原始大小如果太小,  這會降低 tempdb 事務日誌的性能,因此可以設置一個較爲合理的大小數值。

收縮日誌

DBCC SHRINKFILE 可以收縮日誌,但是日誌沒有截斷,收縮日誌不會有效果。日誌可以設置爲自動收縮,不建議這樣做。

建議

建議爲日誌文件分配一個接近於最終所需大小的 size 值,使用所需增量實現最佳 VLF 分發,並且還要分配一個相對較大的自動增長值。

建議增長值設置爲256M-512M 之間

日誌截斷

日誌截斷主要用於阻止日誌填充。 日誌截斷從 SQL Server 數據庫的邏輯事務日誌中刪除不活動的虛擬日誌文件,釋放邏輯日誌中的空間以便物理事務日誌重用這些空間。 如果事務日誌從不截斷,它最終將填滿分配給物理日誌文件的所有磁盤空間。 但是,在截斷日誌前,必須執行檢查點操作。 檢查點將當前內存中已修改的頁(稱爲“髒頁”)和事務日誌信息從內存寫入磁盤。 執行檢查點時,事務日誌的不活動部分將標記爲可重用。 此後,日誌截斷可以釋放不活動的部分。

如何控制事務持續性

您作爲 DBA,可以控制用戶是否可通過以下語句對數據庫使用延遲事務持續性。 您必須使用 ALTER DATABASE 來設置延遲持續性設置。


ALTER DATABASE … SET DELAYED_DURABILITY = { DISABLED | ALLOWED | FORCED }    

DISABLED  [默認] 使用此設置時,不管提交級別設置如何 (DELAYED_DURABILITY=[ON | OFF]),對數據庫提交的所有事務都是完全持久事務。 無需更改和重新編譯存儲過程。 這樣能確保任何數據都不會因延遲持續性面臨風險。   

ALLOWED  使用此設置時,每個事務的持續性都在事務級別確定 - DELAYED_DURABILITY = { OFF | ON }。 

FORCED  使用此設置,對數據庫提交的每個事務都是延遲持久事務。 無論事務指定完全持久 (DELAYED_DURABILITY = OFF) 還是不進行任何指定,事務都是延遲持久事務。 當數據庫適合使用延遲事務持續性,並且您不希望更改任何應用程序代碼時,此設置很有用。

使用DISABLED 在大寫入的時候會對性能有影響。所以而已採取 ALLOWED允許延遲寫入,這樣就可以提高性能。 面臨的風險是:

發生災難性事件(如服務器崩潰)時,將丟失已提交但未保存到磁盤的所有事務的數據。 根據數據庫中的任何表(持久內存優化或基於磁盤)執行完全持久的事務時,或調用 sp_flush_log 時,延遲的持久事務保存到磁盤。 如果你在使用延遲的持久事務,那麼你可能想要在數據庫中創建一個小型表,你可定期更新該表或調用 sp_flush_log ,以保存所有未完成的已提交事務。 事務日誌還會在變滿時刷新,但這難以預測,也無法進行控制。   

  對於延遲的持久性,  SQL Server的意外關閉和預期關閉/重新啓動沒有區別。 與災難性事件類似,應制定針對數據丟失的計劃。 在進行計劃的關閉/重新啓動時,一些尚未寫入磁盤的事務可能會首先保存到磁盤,但不應對其進行計劃。 雖然計劃了關閉/重啓,但無論是否計劃,都會像災難性事件一樣丟失數據。

關於恢復模式

SQL Server有三種恢復模式,參加下表

恢復模式Description工作丟失的風險能否恢復到時點?
Simple無日誌備份。   自動回收日誌空間以減少空間需求,實際上不再需要管理事務日誌空間。 簡單恢復模式不支持要求事務日誌備份的操作。 在簡單恢復模式中不能使用以下功能:   -日誌傳送   -AlwaysOn 或數據庫鏡像   -沒有數據丟失的介質恢復   -時點還原最新備份之後的更改不受保護。 在發生災難時,這些更改必須重做。只能恢復到備份的結尾。
Full需要日誌備份。   數據文件丟失或損壞不會導致丟失工作。   可以恢復到任意時點(例如應用程序或用戶錯誤之前)。 正常情況下沒有。   如果日誌尾部損壞,則必須重做自最新日誌備份之後所做的更改。如果備份在接近特定的時點完成,則可以恢復到該時點。
大容量日誌需要日誌備份。   是完整恢復模式的附加模式,允許執行高性能的大容量複製操作。   通過使用最小方式記錄大多數大容量操作,減少日誌空間使用量。 如果在最新日誌備份後發生日誌損壞或執行大容量日誌記錄操作,則必須重做自該上次備份之後所做的更改。   否則不丟失任何工作。可以恢復到任何備份的結尾。 不支持時點恢復。

根據上表,所有重要的業務系統,除了測試和開發環境,我強烈建議大家使用完整恢復模式

日誌備份

在創建任何日誌備份之前,您必須至少創建一個完整備份。 然後,可以隨時備份事務日誌,除非已備份此日誌。

建議經常執行日誌備份,這樣既可儘量減少丟失工作的風險,也可以截斷事務日誌。 

數據庫管理員通常偶爾(如每週)會創建完整數據庫備份,還可以選擇以較短間隔(如每天)創建一系列差異備份。 與數據庫備份無關,數據庫管理員可以比較頻繁地創建事務日誌備份。 對於給定的備份類型,最恰當的備份間隔取決於一系列因素,如數據的重要性、數據庫的大小和服務器的工作負荷。 有關實現好策略的詳細信息

例如可以這樣做:

Time事件
上午 8:00備份數據庫。
中午12:00備份事務日誌。
下午 4:00備份事務日誌。
晚上 6:00備份數據庫。
晚上 8:00備份事務日誌。

日誌備份建議

  • 在備份鏈裏面如果任何事務日誌損壞,則最新有效備份以後執行的工作將丟失。 因此,我們強烈建議您將日誌文件存儲在容錯的存儲設備中。

  • 如果數據庫已損壞,或者你要還原數據庫,建議你創建一個 結尾日誌備份 ,使你可以將數據庫還原到當前時間點。

  • 默認情況下,每個成功的備份操作都會在 SQL Server 錯誤日誌和系統事件日誌中添加一個條目。 如果非常頻繁地備份日誌,這些成功消息會迅速累積,從而產生一個巨大的錯誤日誌,這樣會使查找其他消息變得非常困難。 在這些情況下,如果任何腳本均不依賴於這些日誌條目,則可以使用跟蹤標誌 3226 取消這些條目。

  • 請經常進行日誌備份,其頻率應足夠支持業務需求,尤其是對損壞的日誌存儲可能導致的數據丟失的容忍程度。

  • 適當的日誌備份頻率取決於您對工作丟失風險的容忍程度與所能存儲、管理和潛在還原的日誌備份數量之間的平衡。 實現恢復策略時,請考慮必需的 RTO 和 RPO,特別是日誌備份頻率。

  • 每 15 到 30 分鐘進行一次日誌備份可能就已足夠。 但是如果您的業務要求將工作丟失的風險最小化,請考慮進行更頻繁的日誌備份。 頻繁的日誌備份還有增加日誌截斷頻率的優點,其結果是日誌文件較小。

總結

說了這麼多,大多都是抄的 Docs,重要的事情是有3件

1、數據庫一定使用完整恢復模式

2、一定要備份數據庫日誌

3、數據庫日誌一定要監視和管理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章