我理解的MySQL Double Write,mysqldouble
沒有Double Write特性的時候
更新資料後,會將dirty page放到innodb buffer cache中。此時頁的checksum值會發生變化。
頁的頭部fileheader部分有checksum項,名為file_page_space_or_checksum。
頁的尾部filetailer部分也有用來比較checksum的項,名為file_page_end_lsn。
它們使用特殊的checksum函數來比較,以此來驗證頁的完整性。
這裡我們簡單的理解為等值比較。
這個時候執行重新整理磁碟操作,16KB的頁,如果唯寫了其中的8KB,這時候發生了意外狀況,伺服器掉電、MySQL樣本突然停掉。這時候就會發生partial page write的問題,即只有頁的部分資料同步到了磁碟上面。
checksum無法通過。
其實MySQL的Innodb以及Oracle資料庫的redo log,不是記錄純物理的操作,而是物理和邏輯結合的日誌。(這樣可以減少redo的產生)
物理到page,也就是page具體在硬碟上的具體位置。
後面對於page的操作,則是根據自己的格式邏輯儲存的(應用的時候需要通過特定的解析函數),比如說向page裡面插入一條記錄。
當然Oracle資料庫也是類似的,物理,只到block層級。
所以說,當page 損壞之後,其實應用redo是沒有意義的。
這時候無法使用redo來恢複,因為原始頁已經損壞了.
會發生資料丟失。
當有doublewrite 特性以後
寫髒資料到磁碟的時候,會先通過memcpy函數將dirty page拷貝到大小為2MB 的double write buffer記憶體地區中。
然後double write buffer第一步先將這2MB的資料每次1MB寫入到共用資料表空間中分配的double write地區中。
第二步才將資料頁寫到資料檔案中去。
當第二步過程中發生故障,也就是發生partial page write的問題。
先檢查頁內的checksum是否相同。
不一致,則直接從doublewrite中恢複。
當然,如果頁的checksum通過,但是與doublewrite中的checksum不同,則可以直接應用redo log來執行恢複操作。
本文只介紹關於double write相關的內容,崩潰恢複的過程要複雜的多,想要瞭解更多可以到下面的連結中找到答案。
參考資料:
MySQL資料庫InnoDB儲存引擎Log漫遊
http://www.uml.org.cn/sjjm/201205222.asp
Innodb Double Write
http://www.percona.com/blog/2006/08/04/innodb-double-write/
Configuration of the Doublewrite Buffer
http://www.percona.com/doc/percona-server/5.5/performance/innodb_doublewrite_path.html?id=percona-server:features:percona_innodb_doublewrite_path
InnoDB Crash Recovery 流程源碼實現分析
http://hedengcheng.com/?p=183