同Oracle一樣,SQL Server在非一致性關閉的時候也會進行實例恢復(Instance Recovery),本文根據stack overflow的文章介紹一些SQL Server實例恢復的知識。 原文鏈接:https://stackoverflow.com/questions/4193273 ...
同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,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 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區域。