文章出處

同Oracle一樣,SQL Server在非一致性關閉的時候也會進行實例恢復(Instance Recovery),本文根據stack overflow的文章介紹一些SQL Server實例恢復的知識。

原文鏈接:https://stackoverflow.com/questions/41932735/sql-server-instance-recovery

關于Oracle的實例恢復參考之前的博文:http://www.cnblogs.com/leohahah/p/6973600.html

首先看一下SQL Server中事務日志的作用:

在SQL Server數據庫中,事務日志用于記錄事務在Buffer Cache中的做的頁更改。

當我們更新一些數據時,數據庫會把相關數據頁的前鏡像和后鏡像都記錄在事務日志中,并為每個事務生成一個唯一的LSN(log seq number),在檢查點發生時SQL Server確保檢查點LSN之前的臟塊被全部寫入到磁盤。因此SQL Server的事務日志兼有redo和undo的作用。

但是,如果我們的數據庫被強制關閉或者服務器異常掉電重啟,數據庫就將處于非一致性的狀態(沒業務的庫除外),這意味檢查點之后的所有事務(無論是提交還是未提交的),都出現了異常,提交的事務可能臟塊未被寫入磁盤,未提交的長事務可能有一部分臟塊已經被寫入到磁盤,數據庫必須處于一致狀態才能被正常打開,因此此時必須進行實例恢復

SQL Server的實例恢復分兩個階段:

1.前滾

此階段只處理已提交的事務,根據boot page中記錄的檢查點和事務日志的記載,SQL Server重構檢查點之后的內存臟塊并按正常機制提交已提交事務的臟塊。

對未提交事務的臟塊暫時不做操作。

2.回滾

此階段處理未提交的事務,SQL Server根據事務日志中記載的更改塊前鏡像,去覆蓋硬盤上那些未提交事務涉及的數據塊。

總結一下:

1)實例恢復的目的:

  • 將所有已提交事務的臟塊寫入磁盤。
  • 回滾未提交的事務。
  • 將檢查點推進至已被寫入磁盤的事務LSN。

2)實例崩潰之前:

  • 一些已提交的事務被事務日志記錄,但是臟塊未被寫入到磁盤
  • 一些未提交的長事務中的臟塊已經被寫入到磁盤
  • 一些未提交的事務,其日志還留在log buffer中未被寫入到磁盤中的事務日志文件。

3)實例恢復階段:

  • Log buffer中所有未提交事務的日志在掉電時全部被清空。(已提交事務的日志默認被寫入了磁盤事務日志文件)
  • 從boot page中識別出上一個檢查點,作為實例恢復的起點。
  • 在前滾階段,SQL Server根據事務日志的記錄對所有臟塊進行重現。(無論是提交還是未提交的事務)然后將已提交事務的臟塊寫入磁盤,對未提交事務的臟塊暫不作操作。
  • 在回滾階段,SQL Server根據事務日志中記載的前鏡像對所有未提交的事務進行回滾。
  • 更新boot page中的檢查點LSN和事務日志中的LSN。

在以上的介紹中我們提到了boot page,那么什么是boot page呢?

每個數據庫都會有一個記錄數據庫重要信息的頁,只有一頁一般是 PRIMARY filegroup的第9個頁。我們可以使用如下命令查看這一頁的信息:

DBCC TRACEON (3604);
go
DBCC PAGE ('test',1,9,3)
go
關于DBCC PAGE的用法這里解釋一下:
dbcc page ( {'dbname' | dbid}, filenum, pagenum [, printopt={0|1|2|3} ])
The printopt parameter has the following meanings:
0 - print just the page header
1 - page header plus per-row hex dumps and a dump of the page slot array (unless its a page that doesn't have one, like allocation bitmaps)
2 - page header plus whole page hex dump
3 - page header plus detailed per-row interpretation

檢查點LSN被記錄在boot page中,這是實例恢復的起點,如果這個page無法被訪問,那么數據庫就不能被附加,打開,或者做其他任何操作。檢查點LSN只會被記錄在bootpage中,因此這是一個對于實例恢復來說不可或缺的頁。

對于SQL Server中檢查點的解釋:

當檢查點發生時,無論這個檢查點是如何觸發的(手動執行檢查點命令,或者數據庫執行差異備份,或者數據庫自動生成的檢查點),數據庫都會做以下操作:

  • 所有的臟塊都被寫入磁盤,無論事務是否已提交。
  • 在這些臟塊被寫入磁盤之前,所有關于這些臟塊更改的事務日志也要被從log buffer中寫入到磁盤,這樣可以確保實例恢復的有效性和有序性,這個操作被稱作write-ahead logging(日志先寫),日志被寫入硬盤的操作是嚴格按時間序列化的,不可能以事務為單位來離散的寫入到磁盤,因此某個臟塊的寫入磁盤操作,可能引發log buffer中一些之前的、與本臟塊無關的事務日志也被寫入磁盤。但這是有好處的,事務日志總是被越早寫入磁盤越好。
  • 檢查點的LSN會被記錄到數據庫boot page中的dbi_checkptLSN區域。
 
這里可以復習一些Oracle的檢查點機制,也是CKPT進程觸發DBWR寫臟塊,同時如果要寫的臟塊的scn大于LGWR的scn,DBWR也會觸發LGWR把要寫的臟塊的相關log buffer寫入redo文件中,與SQL Server日志先寫的機制相似。

文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()