資料庫的物理儲存會分成許多個頁(Page),記錄都儲存在頁中,資料每一次IO,操作的最小單位是一個頁。資料庫執行時,會在記憶體中維護一個緩衝區(Buffer Pool)。緩衝區快取部分的頁(因為記憶體有限,所有不能把所有資料都快取進來)。每次對資料的操作,都需要把磁碟中的頁讀入緩衝區,然後再進行操作;如果緩衝區中有對應的頁,就不需要讀磁碟。如果資料庫要讀入一個頁,而此時需要緩衝區已經被用完了,這個時候就要替換出一個頁面,騰出一塊記憶體給新讀入的頁面。如果被換出的頁被改過(在記憶體中每個頁會有個Dirty標記,標識當前頁面是否被修改過),就要把記憶體頁寫入到磁碟中。
資料庫為了實現事務,需要併發控制和恢復機制。
恢復機制,可以用log實現,多采用steal(未提交的資料可以寫入磁碟),no-force(提交的資料可以不寫入磁碟)策略。
併發控制,現在的多數資料庫用MVCC(MVCC+2PL或MVCC+SSI),由於steal、no-force策略,這個部分完全就相當於在記憶體中做,直接更新的是記憶體頁中的元組。只有發生頁換出,或是checkpoint(定期的刷髒頁)時,才會寫磁碟。
所以,不管提交之前還是提交之後,資料在記憶體中,或是被寫入磁碟,都是有可能的。
補充說明下恢復機制。以上是針對儲存元組的頁面和緩衝區來說的,log還是要在接交時寫入磁碟的,以保證已提交的事務是持久化的。
以MySQL為例,MySQL使用REDO和UNDO來實現恢復。其中,REDO 為了重做對資料更改儲存的資訊,用於恢復;UNDO是與事務相關的, 為了撤銷對資料更改儲存的資訊,用於回滾。每一條REDO日誌記錄都有一個LSN(Log Sequence NO) 日誌號,一個遞增的64位整數,一個LSN表示一個redo log結構。
在三個階段涉及到日誌的操作,分別是寫入資料時,事務提交時,資料庫恢復時。
一)寫入資料,以update為例, Insert與之類似
1.計算更新後tuple到原tuple的delta資訊,把這個delta複製到rollback segment中的undo
2.寫redo log,記錄對rollback segment的更改
3.把buffer pool中的對應tuple更新成新值,把新值的rollback pointer指向第1部生成的undo
4.寫redo log,記錄對資料page的更改
5.將page改成dirty
二)事務提交
force log, flush當前事務的redo log到磁碟
三)資料庫恢復
1.啟動開始時檢測是否發生崩潰
2.定位到最近的一個checkpoint
3.定位在這個checkpoint flush到磁碟的資料,檢查checksum。如果不正確,說明這個頁在上次寫入是不完整的,從doublewrite buffer裡把正確的page讀出來,更新到buffer中的page
4.分析redo log,標識出未提交事務
5.順序執行redo
6.rollback未提交的事務
資料庫的物理儲存會分成許多個頁(Page),記錄都儲存在頁中,資料每一次IO,操作的最小單位是一個頁。資料庫執行時,會在記憶體中維護一個緩衝區(Buffer Pool)。緩衝區快取部分的頁(因為記憶體有限,所有不能把所有資料都快取進來)。每次對資料的操作,都需要把磁碟中的頁讀入緩衝區,然後再進行操作;如果緩衝區中有對應的頁,就不需要讀磁碟。如果資料庫要讀入一個頁,而此時需要緩衝區已經被用完了,這個時候就要替換出一個頁面,騰出一塊記憶體給新讀入的頁面。如果被換出的頁被改過(在記憶體中每個頁會有個Dirty標記,標識當前頁面是否被修改過),就要把記憶體頁寫入到磁碟中。
資料庫為了實現事務,需要併發控制和恢復機制。
恢復機制,可以用log實現,多采用steal(未提交的資料可以寫入磁碟),no-force(提交的資料可以不寫入磁碟)策略。
併發控制,現在的多數資料庫用MVCC(MVCC+2PL或MVCC+SSI),由於steal、no-force策略,這個部分完全就相當於在記憶體中做,直接更新的是記憶體頁中的元組。只有發生頁換出,或是checkpoint(定期的刷髒頁)時,才會寫磁碟。
所以,不管提交之前還是提交之後,資料在記憶體中,或是被寫入磁碟,都是有可能的。
補充說明下恢復機制。以上是針對儲存元組的頁面和緩衝區來說的,log還是要在接交時寫入磁碟的,以保證已提交的事務是持久化的。
以MySQL為例,MySQL使用REDO和UNDO來實現恢復。其中,REDO 為了重做對資料更改儲存的資訊,用於恢復;UNDO是與事務相關的, 為了撤銷對資料更改儲存的資訊,用於回滾。每一條REDO日誌記錄都有一個LSN(Log Sequence NO) 日誌號,一個遞增的64位整數,一個LSN表示一個redo log結構。
在三個階段涉及到日誌的操作,分別是寫入資料時,事務提交時,資料庫恢復時。
一)寫入資料,以update為例, Insert與之類似
1.計算更新後tuple到原tuple的delta資訊,把這個delta複製到rollback segment中的undo
2.寫redo log,記錄對rollback segment的更改
3.把buffer pool中的對應tuple更新成新值,把新值的rollback pointer指向第1部生成的undo
4.寫redo log,記錄對資料page的更改
5.將page改成dirty
二)事務提交
force log, flush當前事務的redo log到磁碟
三)資料庫恢復
1.啟動開始時檢測是否發生崩潰
2.定位到最近的一個checkpoint
3.定位在這個checkpoint flush到磁碟的資料,檢查checksum。如果不正確,說明這個頁在上次寫入是不完整的,從doublewrite buffer裡把正確的page讀出來,更新到buffer中的page
4.分析redo log,標識出未提交事務
5.順序執行redo
6.rollback未提交的事務