MySQL 特性:Double Write


1.什么是double write
  首先要明白double write這個特性是針對誰的,日志or臟數據?
  明白的是臟數據,是內存中修改后的數據頁,這些數據頁修改后和磁盤上存儲的原數據不一致了,稱為臟數據。為了數據的持久性,這些臟數據需要刷新到磁盤上,使修改永久的保存,而double write就產生在將臟數據刷盤的過程中。刷盤是一份臟數據寫到共享表空間,一份寫到真正的數據文件永久的保存。寫了兩次臟數據,就叫double wriete。
 
2.為什么要有double write
  很多人疑問,為啥寫兩次,刷一次數據文件保存數據不就行了,寫共享表空間是啥意思嘛。共享表空間是在ibdbata文件中划出2M連續的空間,專門給double write刷臟頁用的,說白了就是磁盤上2M連續空間。
  MySQL的數據頁默認是16k,對數據頁的校驗也是按16k計算的。而操作系統的數據頁默認是2k或者4k,IO操作是按系統頁為單位就行讀寫的。這就可能出現一種情況,數據庫對一個16k的數據頁修改后,操作系統開始進行寫磁盤,每次寫4k,結果剛寫完第一個4k,數據庫掛了。這時候系統一臉懵逼的看着掛掉的數據庫,呆呆的說了句‘這事不怨我’。這時候數據庫重啟時,校驗數據頁,發現有數據頁不完整,就起不來了,即使通過歪門邪道使數據庫起來,也會有一頁的數據丟失。
  為了解決這個問題,double write就應運而生了,為安全而來。簡單來說,修改后的臟頁放到double write buffer區,這個區占用2M內存空間,buffer空間滿或其他條件觸發,使double write buffer存的臟頁先寫到共享表空間,之后在寫入數據文件。這個時候如果寫了不完整的頁,可以用共享表空間中完整的頁加以覆蓋,數據頁完整了,數據庫也就可以拉起了,之后的各種恢復就看redo log的了。提到redo log了,有人可能又會懵逼,不完整的數據頁用redo log恢復唄,搞個double write多此一舉嗎。這時候不得不介紹一下redo log的記錄日志格式了——redo log是按數據塊的方式記錄日志的,差不多類似於臟頁直接放到redo log中,但又不完全相同,不然redo log得多占空間啊。它是根據偏移量來記錄修改了,比如test數據文件的第1025個數據塊的100字節的偏移位置,數據修改為了‘new data’。一個16k的數據塊不可能哪兒哪兒都修改,有可能僅僅修改里面的一個字節,而redo log的工作作風就是:修改哪兒記錄哪兒。這樣,數據頁不完整了,找redo log沒用。
 
3.double write工作流程
  論double write的工作流程,廢話不多說,請直接看圖:先產生臟頁,產生臟頁的過程中會寫redo log,這是第一步。臟頁有了,也就按部就班了。
4.如何利用double write進行恢復
數據恢復有三種情況:
4.1 臟數據寫磁盤成功
  這種情況是最常見的,臟頁刷磁盤99.9%都會成功,但是即使有0.1失敗可能也要做處理,不然數據丟了,數據庫就不安全了,沒有公司願意天天提心吊膽的抱着個定時炸彈。刷盤成功,找檢查點,redo log前滾、回滾就行了。
4.2 共享表空間寫失敗
  如果是寫共享表空間失敗,那么這些數據不會被寫到數據文件,數據庫會認為這次刷盤從沒發生過,MySQL此時會從磁盤載入原始的數據,然后找檢查點,redo log前滾、回滾就行了。
4.3 臟數據刷數據文件失敗
  寫共享表空間成功,但是寫數據文件失敗,在恢復的時候,MySQL直接比較頁面的checksum,如果不對的話,直接從共享表空間的double write中找到該頁的一個最近的副本,將其復制到表空間文件,再應用redo log,就完成了恢復過程。因為有副本所以也不擔心表空間中數據頁是否損壞。
 
5.double write缺陷及改進過程
  太長了,以后再說。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM