SQL SERVER大話存儲結構(5)_SQL SERVER 事務日志解析


 



 
    本系列上一篇博文鏈接: SQL SERVER大話存儲結構(4)_復合索引與包含索引
  


1 基本介紹

    每個數據庫都具有事務日志,用於記錄所有事物以及每個事物對數據庫所作的操作。

    日志的記錄形式需要根據數據庫的恢復模式來確定,數據庫恢復模式有三種:

  • 完整模式,完全記錄事物日志,需要定期進行日志備份。
  • 大容量日志模式,適用於批量操作的數據庫,可以以更壓縮的方式處理日志,需要定期進行日志備份。
  • 簡單模式,也有日志文件,只是該模式下可以通過checkpoint自動重用virtual log file,所以日志文件會處於一直重復使用的過程,保持一定大小,但是,如果有一個事務啟動,很久沒有commit,那么從這個事務開始到最后commit的時間段內的事務日志存儲空間都無法checpoint自動重用,這時,你很可能看到一個很大的日志文件;注意,簡單模式下是無法進行日志備份

    數據庫里邊,任何對數據庫的讀寫都是在內存頁中找到對應的數據也,再做修改,如果內存頁中不存在數據頁,則從磁盤加載如內存中。當一個修改操作發生時,修改的將是內存頁中對應的數據頁面,同時也會實時記錄到日后文件ldf中。那么,什么時候數據會被同步到mdf文件呢,只有以下三種情況:

  • 做checkpoint時,后續會專門整理checkpoint的相應文章;
  • Lazy write運行時,即內存出現壓力,需要把內存中的數據頁寫入到磁盤,騰出內存空間;
  • eager write時,即發生bulk insert和select into操作時。

    DB中的事務日志記錄,可以給我們帶來很多好處,它可以支持以下操作:

  • 恢復個別的事務。
  • 在 SQL Server 啟動時恢復所有未完成的事務。
  • 將還原的數據庫、文件、文件組或頁前滾至故障點。
  • 支持事務復制。
  • 支持高可用性和災難恢復解決方案:AlwaysOn 可用性組、數據庫鏡像和日志傳送。

2 對數據庫啟動的影響

    當數據庫重啟或者還原到最后的時候,數據庫都會進入 recovery狀態,正常情況下,這個狀態持續時間在幾十秒間,但是特殊情況下,它會花費非常長的時間,甚至幾個小時,如果這個步驟失敗,數據庫則進入到掛起 suspect狀態,無法正常提供使用。
 
    那么,當數據庫進入 recovery 的時候,它在操作些什么呢?
 
    SQL SERVER日志會記錄所有修改記錄(數據的修改情況,不包含SQL語句),包括Begin Transaction和Commit / Rollback Transaction 操作。由於對事務日志的修改,要比數據文件的修改要快,所有會出現,數據修改更新到了日志文件,但是還沒有落盤到數據文件,那么這個時候數據庫就處於recovery狀態,同時對事務日志最近的一個checkpoint點以后的所有數據修改記錄做以下檢查:
 
    所有檢查結束后,則會對數據庫做一個checkpoint的表示,並寫入事務日志中,表明日志文件跟數據文件已經同步結束,完成了recovery過程,數據庫可正常提供使用。這里需要注意一點,如果你數據庫最近一次checkpoint到現在的修改操作足夠多,那么將會耗費相對較長時間來檢查,同時也能夠在 error log中看到百分比標識的recovery完成進展,避免漫無目的的等待。
Error Log的檢查,可以通過圖形界面(見下圖)查看當前日志,也可以運行xp_readerrorlog 查詢。
 1 /*  2 xp_readerrorlog參數說明  3 1. 存檔編號  4 2. 日志類型(1為SQL Server日志,2為SQL Agent日志)  5 3. 查詢包含的字符串  6 4. 查詢包含的字符串  7 5. LogDate開始時間  8 6. LogDate結束時間  9 7. 結果排序,按LogDate排序(可以為降序"Desc" Or 升序"Asc"),默認升序 10 */ 11 12 Exec xp_readerrorlog 0,1,Null,Null,'2017-02-16 10:53:32.300','2017-02-16 12:53:32.300'

 

     假設出現這種情況,由於上線的重要程度遠遠重要過 數據丟失的情況,並且你跟所有部門溝通確認 可以承擔 data file跟log file之間的差異數據的丟失,那么你可以按以下步驟操作,嚴重建議不要這么操作,因為會帶來不可預估的數據丟失情況,如果你命懸一線,真打算放棄這部分數據,那么,可以按照以下操作:
 1 #設置數據庫單用戶  2 alter database backupdb set single_user with rollback immediate  3  4 #設置數據庫緊急狀態  5 alter database backupdb set emergency with rollback immediate  6  7 #獲取事務日志的物理名和邏輯名后,重建日志文件  8 select name,physical_name from sys.master_fiels where database_id=db_id('backupdb')  9 alter database backupdb rebuild log on (name='事務日志的邏輯名',filename='事務日志的物理名詞') 10 11 #設置數據庫online 12 alter database backupdb set online with rollback immediate 13 14 #設置數據庫為多用戶 15 alter database backupdb set multi_user with rollback immediate

3 日志文件添加方式

    日志記錄在 后綴名為 ldf的文件,允許有多個日志文件,但是不會並發分開記錄日志,而是使用填充滿一個日志文件后,再轉向一個日志文件,線性操作日志文件。
    可以通過下方來添加 ldf文件,需要注意幾個地方:
  • 初始大小,建議直接設置為 截斷日志的期間內最大值,比如,某DB 恢復模式是完整模式,每隔半個小時做一次事務日志備份且截斷日志,那么設置 日志文件大小的時候,取業務高峰期 每半小時的日志增長 最大值是5G,則可設置初始大小為 5G-7G之間;
  • 增長大小,無論是 按比例增長還是按照MB增長,都不要設置過小,建議每次增長在100Mb左右,減少使用到自動增長,在最初設置的初始大小就滿足其增長需求 ,如果開始設置的 初始大小 偏小,不滿足,可以挑一個業務低峰期,修改變大初始大小。每一次文件自動增長期間,都會對寫入的日志造成堵塞,雖然時間很短,但是如果增長頻繁,則會影響數據庫操作;
  • 自動增長,建議設置為自動增長,但是前提定期監控日志的增長情況,避免磁盤空間不足,同時,如果恢復模式是 完整模式或者大容量模式,還需定期做日志備份截斷日志,避免 事務日志已滿的9002錯誤;
  • 路徑選擇,建議與 mdf 文件放在不同的磁盤上,分散IO,若是磁盤讀寫瓶頸不大,則可放在一個磁盤上;
添加方式有2種,如下:
 1 USE [master]  2 GO  3 ALTER DATABASE [backupdb]  4 ADD LOG FILE (  5 NAME = N'backupdb_log_1',  6 FILENAME = N'D:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\backupdb_log_1.ldf' ,  7 SIZE = 524288KB ,  8 MAXSIZE = 1048576KB ,  9 FILEGROWTH = 10240KB 10  ) 11 GO

4 物理結構

     數據庫的事務日志映射在一個或者多個的物理文件上,從概念上講,日志文件是一系列的日志記錄;從物理上講,日志記錄序列被有效的存儲在實現事務日志的物理文件中。
    SQL Server 數據庫引擎在內部將每一物理日志文件分成多個虛擬日志文件,即VLF(Virtual Log File),虛擬日志文件沒有固定大小,且物理日志文件所包含的虛擬日志文件數不固定。數據庫引擎在創建或擴展日志文件時 動態選擇虛擬日志文件的大小。數據庫引擎嘗試維護少量的虛擬文件。在擴展日志文件后,虛擬文件的大小是現有日志大小和新文件增量大小之和。
    只有當日志文件使用較小的 size 和 growth_increment 值定義時,虛擬日志文件才會影響系統性能。如果這些日志文件由於許多微小增量而增長到很大,則它們將具有很多虛擬日志文件。這會降低數據庫啟動以及日志備份和還原操作的速度。 建議您為日志文件分配一個接近於最終所需大小的size值,並且還要分配一個相對較大的 growth_increment 值。
    管理員不能配置或設置虛擬日志文件的大小或數量,但是 VLF影響系統性能的情況下,可以嘗試縮小,通過收縮日志文件的方式
dbcc loginfo(dbname) 返回的行數,即為 VLF 文件個數,當status為0時,即該文件沒有被使用,還能寫入LOG,2表示已被使用,並且無法重用,這個時候,可以通過 backup Log 的形式,備份並截斷LOG文件,則可以回收 從最后一個0到最近一個2行的空間。
收縮日志文件或者減少VLF文件的方式如下,需要先備份日志文件,才可以有效進行收縮,在沒有備份日志文件的情況下,進行收縮,效果不大。詳見以下代碼:
 
 1 #其行數及為VLF個數,status為0表示文件未用,為2表示已被使用,無法重用  2 dbcc loginfo  3  4 #備份日志  5 BACKUP LOG [backupdb]  6 TO DISK = N'D:\data\20170215_backupdb_log.trn' WITH NOFORMAT, NOINIT, NAME = N'backupdb-事務日志 備份', SKIP, NOREWIND, NOUNLOAD, STATS = 10  7 GO  8  9 #收縮日志文件,根據日志文件名來收縮500Mb,建議收縮大小是合理大小,參考上文的 初始大小 判斷 10 USE [backupdb] 11 GO 12 SELECT name FROM sys.database_files WHERE type_desc='log' 13 DBCC SHRINKFILE (N'jiankong_db_log' , 500) 14 GO 15 16 #其行數及為VLF個數,VLF文件減少 17 dbcc loginfo

    事務日志是一種回繞的文件。假設,數據庫backupdb只有一個ldf文件,且剛好分成了5個虛擬日志,當我們開始使用數據庫的時候,邏輯日志從物理日志的最開始端向末端記錄,如下圖。

    當出現checkpoint的時候,則會標注 最小恢復日志序列號 MinLSN,“MinLSN”是成功進行數據庫范圍內回滾所需的最早日志記錄的日志序列號。如下圖。

 
    在MinLSN之前的所有虛擬日志文件VLF都可以被截斷,數據庫會在以下兩個事件后自行截斷日志:
  • 簡單恢復模式下,在檢查點之后發生。

  • 在完整恢復模式或大容量日志恢復模式下,如果自上一次備份后生成檢查點,則在日志備份后進行截斷(除非是僅復制日志備份)。
    當截斷日志的時候,這些VLF就可以被釋放回收,邏輯日志的開頭也會移動到最后一個被階段VLF文件末端。
     假設這個時候,在MinLSN位置后,發生了一個事務,一直沒有commit,導致VLF3,VLF4,VLF5都被使用,那么就會重用之前回收的VLF文件。
 
 
    正常情況下,如果經常截斷舊的日志記錄,保持邏輯日志的末端不到達邏輯日志的開頭,滿足下一個檢查點之前船艦的所有新日志記錄都有足夠的空間存儲,那么日志文件將永遠不會被填滿,保持一定的大小,可通過定期備份事務日志來達到。
    但是如果,邏輯日志的結尾跟開頭碰面了,那么當磁盤空間足夠的情況下,則按照 自動增大大小 指定的數量 增大日志文件,並在 物理日志文件中添加多個VLF文件;如果磁盤空間不足,比指定的 增量大小 要少,那么就會報錯,出現9002錯誤,導致數據庫無法進行所有寫操作。

5 延遲日志截斷原因

     日志截斷會由於多種因素發生延遲。可查詢sys.databases目錄視圖的 log_reuse_waitlog_reuse_wait_desc 列來發現是什么(如果有)阻止了日志的截斷。 下表對這些列的值進行了說明。
 

6 管理事務日志

    定期監控日志文件的大小跟實際使用大小,以防日志增長異常,占滿磁盤空間,可通過以下兩種方式查看 日志文件使用情況.
1 #查看日志使用情況,文件大小及實際使用大小 2 dbcc sqlperf(logspace) 3 4 #查看文件相關信息 5 select name,physical_name,size*8.0/1024 size_Mb,* from sys.database_files

    定期日志備份,兩個備份的間隔是運行丟失數據的時間跨度,不要過於頻繁備份,會對數據庫IO造成一定影響。

1 BACKUP LOG [backupdb] 2 TO DISK = N'D:\data\20170215_backupdb_log.trn' WITH NOFORMAT, NOINIT, NAME = N'backupdb-事務日志 備份', SKIP, NOREWIND, NOUNLOAD, STATS = 10 3 GO
    事務盡可能短,避免長時間開啟事務,或者忘記commit/roll back;
    解決事務日志已滿問題(9002錯誤)
  • 若是限制了文件最大值,在磁盤空間有剩余的情況下,增加日志文件的大小。
  • 釋放磁盤空間以便日志可以自動增長。
  • 在其他磁盤上添加日志文件。
  • 備份日志后,收縮日志。
  • 將日志文件移到具有足夠空間的磁盤驅動器。

 

 

參考文檔:
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM