【MYSQL】innodb兩次寫(double write)實現解析
在innodb儲存引擎中,有一個叫doublewrite技術模組,是可選的。它透過引數InnoDB_doublewrite的值來控制,如果為0表示不啟用,可以透過show status like "%InnoDB_dblwr%"來檢視,doublewrite技術帶給innodb儲存引擎的是資料頁的可靠性,下面對doublewrite技術進行解析,讓大家充分理解doublewrite是如何做到保障資料頁的可靠性。
一、doublewrite應用場景:
我們知道,innodb的資料頁一般大小是16KB,MySQL存取資料的最小單位也是頁,而作業系統並不能保障一個資料頁的原子性,也就是說當寫入資料時,有可能在一個頁中寫入一半時(比如8K)資料庫當機,這種情況稱為部分寫失效(partial page write),從而導致資料丟失。
大家也許會問,難道我不可以根據redo log進行資料恢復嗎?答案是肯定的也是否定的,要分為兩種情況:1、資料庫當機,物理檔案完好無損,是可以透過redo log進行崩潰恢復。2、資料庫當機,正在重新整理到磁碟的頁發生partial page write,而正好在磁碟上的這個資料頁由於當機發生損壞,這時就無法透過redo log進行資料恢復了,為什麼?我們必須要清楚的認識到,redo log裡記錄的是對頁的物理操作!比如一條redo記錄"page number xx,偏移量 800 寫記錄 “this is abc”",那當頁損壞時,這條redo記錄還有意義嗎?於是在這種特殊情況下,doublewrite就派上用場啦!
二、doublewrite體系結構及工作流程:
doublewrite由兩部分組成,一部分為記憶體中的doublewrite buffer,其大小為2MB,另一部分是磁碟上共享表空間(ibdata x)中連續的128個頁,即2個區(extent),大小也是2M。doublewrite工作流程如下:
1、當一系列機制(main函式觸發、checkpoint等)觸發資料緩衝池中的髒頁進行重新整理時,並不直接寫磁碟,而是會透過memcpy函式將髒頁先複製到記憶體中的doublewrite buffer,之後透過doublewrite buffer再分兩次、每次1MB順序寫入共享表空間的物理磁碟上。
2、馬上呼叫fsync函式,同步髒頁進磁碟
由於在這個過程中,doublewrite頁的儲存時連續的,因此寫入磁碟為順序寫,效能很高;完成doublewrite後,再將髒頁寫入實際的各個表空間檔案,這時寫入就是離散的了。各模組協作情況如下圖(第一步應為髒頁產生的redo記錄logbuffer,然後logbuffer寫入redo log file,為簡化次要步驟直接連線表示):
檢視doublewrite工作情況,可以執行命令:
mysql> show global status like 'innodb_dblwr%'\G
*************************** 1. row ***************************
Variable_name: Innodb_dblwr_pages_written
Value: 61932183
*************************** 2. row ***************************
Variable_name: Innodb_dblwr_writes
Value: 15237891
2 rows in set (0.00 sec)
以上資料顯示,doublewrite一共寫了 61932183個頁,一共寫了15237891次,從這組資料我們可以分析,之前講過在開啟doublewrite後,每次髒頁重新整理必須要先寫doublewrite,而doublewrite存在於磁碟上的是兩個連續的區,每個區由連續的頁組成,一般情況下一個區最多有64個頁,所以一次IO寫入應該可以最多寫64個頁。而根據以上我這個系統Innodb_dblwr_pages_written與Innodb_dblwr_writes的比例來看,大概在4左右,遠遠還沒到64,所以從這個角度也可以看出,系統寫入壓力並不高。
三、崩潰恢復
如果作業系統在將頁寫入磁碟的過程中發生崩潰,如上圖,在恢復過程中,innodb儲存引擎可以從共享表空間的doublewrite中找到該頁的一個最近的副本,將其複製到表空間檔案,再應用redo log,就完成了恢復過程。因為有副本所以也不擔心表空間中資料頁是否損壞。
四、建議
innodb儲存引擎引入double write技術後,引數skip_innodb_doublewrite雖然可以禁止使用doublewrite功能,但還是強烈建議大家使用doublewrite。避免部分寫失效問題,當然,有些檔案系統本身就提供了部分寫失效防範機制,如ZFS檔案系統,在這種情況下,就可以不開啟doublewrite了
一、doublewrite應用場景:
我們知道,innodb的資料頁一般大小是16KB,MySQL存取資料的最小單位也是頁,而作業系統並不能保障一個資料頁的原子性,也就是說當寫入資料時,有可能在一個頁中寫入一半時(比如8K)資料庫當機,這種情況稱為部分寫失效(partial page write),從而導致資料丟失。
大家也許會問,難道我不可以根據redo log進行資料恢復嗎?答案是肯定的也是否定的,要分為兩種情況:1、資料庫當機,物理檔案完好無損,是可以透過redo log進行崩潰恢復。2、資料庫當機,正在重新整理到磁碟的頁發生partial page write,而正好在磁碟上的這個資料頁由於當機發生損壞,這時就無法透過redo log進行資料恢復了,為什麼?我們必須要清楚的認識到,redo log裡記錄的是對頁的物理操作!比如一條redo記錄"page number xx,偏移量 800 寫記錄 “this is abc”",那當頁損壞時,這條redo記錄還有意義嗎?於是在這種特殊情況下,doublewrite就派上用場啦!
二、doublewrite體系結構及工作流程:
doublewrite由兩部分組成,一部分為記憶體中的doublewrite buffer,其大小為2MB,另一部分是磁碟上共享表空間(ibdata x)中連續的128個頁,即2個區(extent),大小也是2M。doublewrite工作流程如下:
1、當一系列機制(main函式觸發、checkpoint等)觸發資料緩衝池中的髒頁進行重新整理時,並不直接寫磁碟,而是會透過memcpy函式將髒頁先複製到記憶體中的doublewrite buffer,之後透過doublewrite buffer再分兩次、每次1MB順序寫入共享表空間的物理磁碟上。
2、馬上呼叫fsync函式,同步髒頁進磁碟
由於在這個過程中,doublewrite頁的儲存時連續的,因此寫入磁碟為順序寫,效能很高;完成doublewrite後,再將髒頁寫入實際的各個表空間檔案,這時寫入就是離散的了。各模組協作情況如下圖(第一步應為髒頁產生的redo記錄logbuffer,然後logbuffer寫入redo log file,為簡化次要步驟直接連線表示):
檢視doublewrite工作情況,可以執行命令:
mysql> show global status like 'innodb_dblwr%'\G
*************************** 1. row ***************************
Variable_name: Innodb_dblwr_pages_written
Value: 61932183
*************************** 2. row ***************************
Variable_name: Innodb_dblwr_writes
Value: 15237891
2 rows in set (0.00 sec)
以上資料顯示,doublewrite一共寫了 61932183個頁,一共寫了15237891次,從這組資料我們可以分析,之前講過在開啟doublewrite後,每次髒頁重新整理必須要先寫doublewrite,而doublewrite存在於磁碟上的是兩個連續的區,每個區由連續的頁組成,一般情況下一個區最多有64個頁,所以一次IO寫入應該可以最多寫64個頁。而根據以上我這個系統Innodb_dblwr_pages_written與Innodb_dblwr_writes的比例來看,大概在4左右,遠遠還沒到64,所以從這個角度也可以看出,系統寫入壓力並不高。
三、崩潰恢復
如果作業系統在將頁寫入磁碟的過程中發生崩潰,如上圖,在恢復過程中,innodb儲存引擎可以從共享表空間的doublewrite中找到該頁的一個最近的副本,將其複製到表空間檔案,再應用redo log,就完成了恢復過程。因為有副本所以也不擔心表空間中資料頁是否損壞。
四、建議
innodb儲存引擎引入double write技術後,引數skip_innodb_doublewrite雖然可以禁止使用doublewrite功能,但還是強烈建議大家使用doublewrite。避免部分寫失效問題,當然,有些檔案系統本身就提供了部分寫失效防範機制,如ZFS檔案系統,在這種情況下,就可以不開啟doublewrite了
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29018063/viewspace-2086098/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql innodb double write概念彙總MySql
- MySQL double writeMySql
- MySQL double write存在意義MySql
- 【MySQL】八、double write 淺析.MySql
- mysql之 double write 淺析MySql
- 敲黑板:InnoDB的Double Write,你必須知道
- InnoDB儲存引擎——兩次寫儲存引擎
- MySQL的Double Write並不難理解MySql
- MySQL的double write和Oracle對比學習MySqlOracle
- MYSQL和INNODB分層實現MySql
- MySQL innodb 事務的實現MySql
- InnoDB MVCC實現原理及原始碼解析MVC原始碼
- Mongodb write寫(增、刪、改)模組原始碼實現MongoDB原始碼
- mysql 5.5引數--innodb_read(write)_io_threadsMySqlthread
- MySQL:MGR 學習(1):寫集合(Write set)MySql
- 搞懂MySQL InnoDB事務ACID實現原理MySql
- MYSQL INNODB中hash查詢表的實現MySql
- mysql [ERROR] InnoDB: ./ibdata1 can't be opened in read-write modeMySqlError
- MySQL innodb 事務的實現(看書筆記)MySql筆記
- MySQL:Innodb DB_ROLL_PTR指標解析MySql指標
- MySQL:Innodb page clean 執行緒 (二) 解析MySql執行緒
- InnoDB索引實現索引
- MySQL:MGR 學習(2):Write set(寫集合)的寫入過程MySql
- MYSQL INNODB 中通用雙向連結串列的實現MySql
- shared_ptr實現多執行緒讀寫copy-on-write執行緒
- MySQL中InnoDB儲存引擎的實現和執行原理MySql儲存引擎
- Cordova + Vue 實現點選兩次退出應用Vue
- MYSQL INNODB 組合索引分支節點資料解析MySql索引
- MySQL Innodb 儲存結構 & 儲存Null值 解析MySqlNull
- ProxySQL實現MySQL讀寫分離MySql
- Amoeba 實現 MySQL 讀寫分離MySql
- MySQL升級WRITE_SET後的一次死鎖分析MySql
- InnoDB行鎖實現方式
- mongodb核心原始碼實現及效能優化系列:Mongodb write寫(增、刪、改)模組原始碼實現MongoDB原始碼優化
- 解析MYSQL BINLOG 二進位制格式(5)--WRITE_ROW_EVENTMySql
- MySQL兩種儲存引擎: MyISAM和InnoDB 簡單總結MySql儲存引擎
- 【轉】Mysql兩種儲存引擎的異同【MyISAM和InnoDB】MySql儲存引擎
- MySQL怎麼實現主從同步和Django實現MySQL讀寫分離MySql主從同步Django