標籤:ima 崩潰 記憶體 logs 有序性 也會 資料 class ceo
同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);goDBCC PAGE (‘test‘,1,9,0)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 header1 - 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 dump3 - 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日誌先寫的機制相似。
SQL Server的執行個體恢複解析