我把所有的信息從這裏臨SQL服務器內部2014
https://www.amazon.com/Pro-Server-Internals-Dmitri-Korotkevitch/dp/1430259620
TL; DR;
恢復模式SIMPLE和FULL不同於SQL Server如何使虛擬日誌文件(VLF)失活。
總結:
1 - 「在SIMPLE恢復模型中,事務日誌的活動部分以VLF開頭,VLF包含最早的活動事務的最舊LSN或最後一個CHECKPOINT」;
2「 - 在完整或是批量日誌恢復模型,事務日誌的活動部分與VLF開始,其中包含最早的以下內容:
LSN最後一個日誌備份的
LSN最早的活動事務
的讀取事務日誌記錄」
LSN =日誌序列號=獨特,自動遞增ID
更詳細的解釋的過程中 LSN
假設這是SQL Server內存模型:
1 - 緩衝池是SQL Server存儲索引,行等內存的地方;
2 - 日誌緩衝區是事務日誌的一小部分(每個數據庫64KB)緩衝區;
3 - 數據文件是SQL Server將存儲索引,行等...在磁盤中的地方;
4 - 事務日誌是......磁盤中的事務日誌。
假設我們有一個數據庫處於以下狀態。
/--------------- IN MEMORY --------------\/------------ IN DISK -----------\
|--------------------------------------------------------------------------|
|Buffer Pool | Log Buffer | Data File |Transaction Log |
|---------------------------|-------------|---------------|----------------|
|Page 1:24312 | |Page: 1:24312 |LSN:7213 |
|IsDirty: False | |LSN: 4845 | |
|LSN: 4845 | |Page: 1:24313 | |
|... | |LSN: 2078 | |
|Page 1:26912 | |... | |
|isDirty:False | |Page: 1:26911 | |
|LSN:1053 | |LSN: 2078 | |
| | |Page: 1:26912 | |
| | |LSN: 2078 | |
|---------------------------|-------------|---------------|----------------|
現在假設進行了一個更改,一個簡單的更新。
第一步是將日誌記錄插入日誌緩衝區。
/--------------- IN MEMORY --------------\/------------ IN DISK -----------\
|--------------------------------------------------------------------------|
|Buffer Pool | Log Buffer | Data File |Transaction Log |
|---------------------------|-------------|---------------|----------------|
|Page 1:24312 |LSN:7214 |Page: 1:24312 |LSN:7213 |
|IsDirty: False |Op:Update |LSN: 4845 | |
|LSN: 4845 |Page:1:24312 |Page: 1:24313 | |
|... |OldLsn:4845 |LSN: 2078 | |
|Page 1:26912 |Row:2 |... | |
|isDirty:False |Tran:T1 |Page: 1:26911 | |
|LSN:1053 |PrevLSN:7141 |LSN: 2078 | |
| | |Page: 1:26912 | |
| | |LSN: 2078 | |
|---------------------------|-------------|---------------|----------------|
,然後更改內存中的數據頁(我只改變IsDirty簡化)
/--------------- IN MEMORY --------------\/------------ IN DISK -----------\
|--------------------------------------------------------------------------|
|Buffer Pool | Log Buffer | Data File |Transaction Log |
|---------------------------|-------------|---------------|----------------|
|Page 1:24312 |LSN:7214 |Page: 1:24312 |LSN:7213 |
|IsDirty: TRUE |Op:Update |LSN: 4845 | |
|LSN: 4845 |Page:1:24312 |Page: 1:24313 | |
|... |OldLsn:4845 |LSN: 2078 | |
|Page 1:26912 |Row:2 |... | |
|isDirty:False |Tran:T1 |Page: 1:26911 | |
|LSN:1053 |PrevLSN:7141 |LSN: 2078 | |
| | |Page: 1:26912 | |
| | |LSN: 2078 | |
|---------------------------|-------------|---------------|----------------|
這一直持續到日誌緩衝區已滿,或事務被提交。 提交在日誌緩衝區中生成另一個條目,其中OP是提交併將整個緩衝區刷新到磁盤。
/--------------- IN MEMORY --------------\/------------ IN DISK -----------\
|--------------------------------------------------------------------------|
|Buffer Pool | Log Buffer | Data File |Transaction Log |
|---------------------------|-------------|---------------|----------------|
|Page 1:24312 | |Page: 1:24312 |LSN:7213 |
|IsDirty: TRUE | |LSN: 4845 | |
|LSN: 4845 | |Page: 1:24313 |LSN:7214 |
|... | |LSN: 2078 |<ALL PROPERTIES>|
|Page 1:26912 | |... | |
|isDirty:False | |Page: 1:26911 |LSN:7215 |
|LSN:1053 | |LSN: 2078 |Op:Commit |
| | |Page: 1:26912 | |
| | |LSN: 2078 |LSN:7216 |
| | | |Op:Checkpoint |
|---------------------------|-------------|---------------|----------------|
此時SQL Server將回答事務成功的客戶端。 值得指出的是內存中的髒頁還沒有被髮送到磁盤。 在這一點上,如果發生了什麼事SQL Server將能夠恢復到這個確切點的所有更改。
這種技術被稱爲預寫日誌記錄和詳細信息,請參閱:
重複歷史超越ARIES
http://www.vldb.org/conf/1999/P1.pdf
在某些時刻檢查點進程將創建刷新緩衝池中的所有髒頁的檢查點操作到磁盤。如上例所示,檢查點操作也出現在事務日誌中。
考慮到這一點,我們可以看到SQL Server如何處理事務日誌。
虛擬日誌文件
的事務日誌的磁盤上是細分在虛擬日誌文件(VLF)。您可以查看運行:
DBCC LOGINFO
最重要的部分就是虛擬日誌文件(VLF)可以被歸類爲有效或無效。
SQL Server只在其恢復模型中使用事務日誌的活動部分。所以簡單和完全之間的區別是當一個VLF變成非活動時。 SQL Server停用VLF是因爲事務日誌是一個環繞文件,這意味着「當邏輯日誌文件的末尾達到物理文件的末尾時,日誌將環繞它」。例如:
/------ACTIVE-----\/----------------INACTIVE----------------\/--------ACTIVE---\
|------------------------------------------------------------------------------|
| | | | | | | | |
| VLF1 | VLF2 | VLF3 | VLF4 | VLF5 | VLF6 | VLF7 | VLF8 |
| | | | | | | | |
|------------------------------------------------------------------------------|
因此,如果由於某種原因沒有VLF變爲無效,則事務日誌將需要無限增長。
處於簡單恢復
回過頭來看看這個例子。在檢查點之後,並且所有內容都刷新到磁盤,SIMPLE恢復中的SQL Server將只維護激活的VLF:
1 - 包含最早的活動事務的最舊的LSN;或
2 - 最後一個檢查點。
例如:
一個檢查點
/------INACTIVE---\/----------------ACTIVE-------\/---------INACTIVE-----------\
|------------------------------------------------------------------------------|
| | | | | | | | |
| VLF1 | VLF2 | VLF3 | VLF4 | VLF5 | VLF6 | VLF7 | VLF8 |
| | | | | | | | |
|------------------------------------------------------------------------------|
^ ^ ^ ^^
| | | | |> End of logical LOG file
| | | |> Current LSN
| | |> Minumin LSN (Oldest Active Transaction)
| |> Last Checkpoint
|> Start of Logical LOG file
邊檢站
/------INACTIVE---------------\/----ACTIVE-------\/---------INACTIVE-----------\
|------------------------------------------------------------------------------|
| | | | | | | | |
| VLF1 | VLF2 | VLF3 | VLF4 | VLF5 | VLF6 | VLF7 | VLF8 |
| | | | | | | | |
|------------------------------------------------------------------------------|
^^ ^^
| | | |> End of logical LOG file
| | |> Current LSN (Checkpoint Occurs)
| |> Minumin LSN (Oldest Active Transaction)
|> Start of Logical LOG file
SQL服務器已經滅活包含最後一個檢查點的VLF3之後之前因爲:
1 - 新檢查點將內存中的所有髒頁面強制到磁盤上。因此,不需要重做存儲在VLF3中的任何更改,因爲最早的活動事務處於VLF4中;
2 - 但是,正因爲如此,我們仍然需要VLF4來支持所有活動事務的回滾。
處於完全恢復
同樣的過程發生在完全恢復,但現在最後的VLF將保持活躍將是最古老的來自:
1 - 最後的日誌備份的LSN;
2-OLDEST ACTIVE TRANSACTION的LSN;或
3 - 讀取事務日誌記錄的進程的LSN。
例如
/------INACTIVE---------------\/----ACTIVE-------\/---------INACTIVE-----------\
|------------------------------------------------------------------------------|
| | | | | | | | |
| VLF1 | VLF2 | VLF3 | VLF4 | VLF5 | VLF6 | VLF7 | VLF8 |
| | | | | | | | |
|------------------------------------------------------------------------------|
^^ ^^ ^
| | | | |> End of logical LOG file
| | | |> Current LSN (Checkpoint Occurs)
| | |> Minumin LSN (Oldest Active Transaction)
| |> Replication log Reader
|> Start of Logical LOG file
在這個例子中,複製日誌讀取迫使VLF4保持活躍
。
或
/------INACTIVE---\/----------------ACTIVE-------\/---------INACTIVE-----------\
|------------------------------------------------------------------------------|
| | | | | | | | |
| VLF1 | VLF2 | VLF3 | VLF4 | VLF5 | VLF6 | VLF7 | VLF8 |
| | | | | | | | |
|------------------------------------------------------------------------------|
^^ ^ ^^ ^
| | | | | |> End of logical LOG file
| | | | |> Current LSN (Checkpoint Occurs)
| | | |> Minumin LSN (Oldest Active Transaction)
| | |> Replication log Reader
| |> Last Transaction Log Backup
|> Start of logical LOG file
,並在這個例子中,「最後的事務日誌備份」被強迫VLF3保持活躍。
我希望這些有助於更好地理解SQL Server的工作原理。
正如@Bee_Riii所提到的,一旦事務被提交,簡單恢復將不會保留日誌。怎麼運行的?在我的例子中,如果我用COMMIT替換ROLLBACK,日誌仍然存在。 – p2k
是什麼讓你認爲日誌仍然存在?由於日誌文件的大小?如果文件的大小已經增大並不意味着它有內部日誌,這意味着文件不夠大,無法寫入sql server必須寫入的所有日誌,因此文件已經增長。磁盤上的日誌文件大小和該文件中的日誌是兩回事。 –
明白了,當我試圖收縮日誌文件時,它說93%的可用空間可用。這意味着它不是日誌數據而是它的文件大小。這清除了我的懷疑。謝謝 – p2k