了解MySQL之Doublewrite Buffer使用
前言
上一篇文章MySQL之Adaptive Hash Index詳解我們學(xué)習(xí)了InnoDB Adaptive Hash Index自適應(yīng)哈希索引的工作原理。
其本質(zhì)是將頻繁訪問數(shù)據(jù)頁的索引鍵值以“Key”放在緩存中,“Value”為該索引鍵值匹配完整記錄所在頁面(Page)的位置,通過縮短尋路路徑(Search Path)從而提升MySQL查詢性能的一種方式。
今天我們就學(xué)習(xí)了解一下Doublewrite Buffer是什么?工作原理是怎樣的?(雙寫緩沖區(qū),縮寫:DWB)
一、不同程序的page
這里我們需要知道的是Doublewrite Buffer被MySQL放在官檔目錄“磁盤結(jié)構(gòu)”中了,但真實情況是Doublewrite Buffer是內(nèi)存+磁盤的結(jié)構(gòu)。

官檔地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html
1.1 Linux系統(tǒng)的Page OR MySQL的Page 大小對比
操作系統(tǒng)可以看成是一個程序,作為程序而言,都有最小處理單位的說法,我們常見的服務(wù)器一般都是Linux操作系統(tǒng),對應(yīng)文件系統(tǒng)的頁(OS Page)就可以看成是Linux操作系統(tǒng)與文件系統(tǒng)交互的最小單位。
可以通過下面的命令來查看:
[root@mysql2 ~]# getconf PAGESIZE 4096
通過結(jié)果可以看出,Linux文件系統(tǒng)頁(OS Page)的大小是4KB。
同樣地,MySQL作為一個程序也是有最小交互單位的,即InnoDB Buffer Pool能處理的最小單位,可以通過以下SQL命令查看:
mysql> show variables like '%innodb_page_size%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | innodb_page_size | 16384 | +------------------+-------+ 1 row in set (0.01 sec)
如上,MySQL頁(Page)大小默認(rèn)為16KB
1.2 不同大小Page的程序在交互過程中會出現(xiàn)什么問題
一般情況下,除了操作系統(tǒng)的頁(OS Page)為4KB之外,其余程序的頁(Page)都會大于等于操作系統(tǒng)的頁大小,比如,Oracle的Page大小為8KB。
MySQL的Page大小也可以通過上面innodb_page_size參數(shù)指定(5.6版本以前,不可調(diào)整;5.6版本時,可自定義為8KB、4KB,但不能調(diào)大;5.7版本以后,才可以改成32KB、64KB。我們使用默認(rèn)值即可。
我們知道操作系統(tǒng)的頁大小和MySQL的頁大小了,而且MySQL程序是跑在Linux操作系統(tǒng)上的,所以可以得出一個結(jié)論:MySQL將Buffer Pool中一頁數(shù)據(jù)刷入磁盤,要寫4個文件系統(tǒng)里的頁。

如上圖所示:
MySQL里Page 1的頁,物理上對應(yīng)磁盤的Page 1、Page 2、Page 3、Page 4四個頁,假設(shè)MySQL內(nèi)Page 1的頁準(zhǔn)備刷入磁盤,才刷了3個文件系統(tǒng)里的頁,掉電了,則會出現(xiàn)重啟后,MySQL內(nèi)Page 1的頁,物理上對應(yīng)磁盤上的Page 1、Page 2、Page 3三個頁,數(shù)據(jù)完整性被破壞。(Redo Log無法修復(fù)這類“頁數(shù)據(jù)損壞”的異常,修復(fù)的前提是“頁數(shù)據(jù)正確”并且Redo日志正常)
二、Doublewrite Buffer概念
針對上面出現(xiàn)的情況,如何解決這類“頁數(shù)據(jù)損壞”的問題呢?
很容易想到的方法是,能有一個“副本”,對原來的頁進行還原,這個存儲“副本”的地方,就是Doublewrite Buffer。
Doublewrite Buffer,它與傳統(tǒng)的“Buffer”又不同,它分為內(nèi)存和磁盤的兩層架構(gòu)。(傳統(tǒng)的“Buffer”,大部分是內(nèi)存存儲;而DWB里的數(shù)據(jù),是需要落地的)
三、Doublewrite Buffer工作流程

如上圖所示,當(dāng)有頁數(shù)據(jù)要刷盤時:
- 頁數(shù)據(jù)先memcopy到DWB的內(nèi)存里;
- DWB的內(nèi)存里的數(shù)據(jù)頁,會先刷到DWB的磁盤上;
- DWB的內(nèi)存里的數(shù)據(jù)頁,再刷到數(shù)據(jù)磁盤存儲.ibd文件上;
DWB為什么能解決“頁數(shù)據(jù)損壞”問題呢?
假設(shè)步驟2掉電,磁盤里依然是Page 1、Page 2、Page 3、Page 4的完整數(shù)據(jù)。只要有頁數(shù)據(jù)完整,就能通過Redo Log還原數(shù)據(jù);假如步驟3掉電,DWB磁盤結(jié)構(gòu)里存儲著完整的數(shù)據(jù)。所以,一定不會出現(xiàn)“頁數(shù)據(jù)損壞”問題。同時寫了DWB磁盤和Data File,總有一個地方的數(shù)據(jù)是OK的
為什么叫Doublewrite?
步驟2和步驟3要寫2次磁盤,這就是“Doublewrite”的由來
能夠通過DWB保證頁數(shù)據(jù)的完整性,但畢竟DWB要寫兩次磁盤,會不會導(dǎo)致數(shù)據(jù)庫性能急劇降低呢?
- 頁數(shù)據(jù)memcopy到DWB的內(nèi)存,速度很快;
- DWB的內(nèi)存fsync刷到DWB的磁盤,屬于順序追加寫,速度也很快;
- 刷磁盤,隨機寫,本來就需要進行,不屬于額外操作;
- 另外,128頁(每頁16K)2M的DWB,會分兩次刷入磁盤,每次最多64頁,即1M的數(shù)據(jù)(所以圖中我們的DWB磁盤結(jié)構(gòu)分為了兩部分),執(zhí)行也是非常之快的。綜上,性能會有所影響,但影響并不大
四、Doublewrite Buffer的參數(shù)
我們使用如下命令查詢
mysql> show variables like '%double%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | innodb_doublewrite | ON | | innodb_doublewrite_batch_size | 0 | | innodb_doublewrite_dir | | | innodb_doublewrite_files | 2 | | innodb_doublewrite_pages | 4 | +-------------------------------+-------+ 5 rows in set (0.01 sec) mysql> show global status like '%dblwr%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Innodb_dblwr_pages_written | 489 | | Innodb_dblwr_writes | 176 | +----------------------------+-------+ 2 rows in set (0.00 sec)
4.1 innodb_doublewrite
Doublewrite Buffer是否啟用開關(guān),默認(rèn)是開啟狀態(tài),InnoDB將所有數(shù)據(jù)存儲兩次,首先到雙寫緩沖區(qū),然后到實際數(shù)據(jù)文件
如果關(guān)閉,需要在my.cnf文件中指定
[mysqld] innodb_doublewrite = off
4.2 Innodb_dblwr_pages_written & Innodb_dblwr_writes
Innodb_dblwr_pages_written是doublewrite寫的總的頁數(shù),即一共寫入了489頁innodb_dblwr_writes是實際寫入的次數(shù)為176
如果兩個計數(shù)的比例遠遠小于64:1,則說明系統(tǒng)寫入壓力并不高。
4.3 innodb_doublewrite_batch_size
- 控制要批量寫入的雙寫頁數(shù)。
- 此變量用于高級性能調(diào)整。
- 默認(rèn)值應(yīng)該適合大多數(shù)用戶(默認(rèn)值是0,最大值是256)
4.4 innodb_doublewrite_dir
- 定義了目錄InnoDB創(chuàng)建雙寫文件。
- 如果未指定innodb_data_home_dir目錄,則在目錄中創(chuàng)建雙寫文件,如果未指定,則默認(rèn)為數(shù)據(jù)目錄。
4.5 innodb_doublewrite_files
- 定義了雙寫文件的數(shù)量。默認(rèn)情況下,為每個緩沖池實例創(chuàng)建兩個雙寫文件。
- 雙寫文件的最大數(shù)量是緩沖池實例數(shù)量的兩倍。(緩沖池實例的數(shù)量由innodb_buffer_pool_instances變量控制)
Doublewrite文件名具有以下格式:
例如,以下雙寫文件是為頁面大小為16KB和單個緩沖池的MySQL實例創(chuàng)建的:
#ib_丨page_size_file_丨number.dblwr
所以我們的DWB文件就被創(chuàng)建成下面的模樣:
[root@mysql2 data]# ll \#ib_16384_* -rw-r----- 1 mysql mysql 327680 5月 4 12:40 #ib_16384_0.dblwr -rw-r----- 1 mysql mysql 8716288 4月 26 16:54 #ib_16384_1.dblwr
4.6 innodb_doublewrite_pages
控制每個線程雙寫頁的最大數(shù)目。如果未指定值,innodb_doublewrite_pages則設(shè)置為該innodb_write_io_threads值。
此變量用于高級性能調(diào)整。默認(rèn)值應(yīng)該適合大多數(shù)用戶。(最小值和默認(rèn)值一樣,都是innodb_write_io_threads的值,最大值是256)
今天主要講解了MySQL InnoDB Doublewrite Buffer的工作原理,通過流程圖的方式來說明Doublewrite Buffer的工作流程,偏理論的知識,內(nèi)容比較少也很好理解,大家理解記憶即可,面試也會遇到這個知識點。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL server has gone away的問題解決
本文主要介紹了MySQL server has gone away的問題解決,意思就是指client和MySQL server之間的鏈接斷開了,下面就來介紹一下幾種原因及其解決方法,感興趣的可以了解一下2024-07-07
MySQL的LEFT JOIN表連接的進階學(xué)習(xí)教程
這篇文章主要介紹了MySQL的LEFT JOIN表連接的進階學(xué)習(xí)教程,包括對左連接的查詢效率分析以及相關(guān)建議,需要的朋友可以參考下2015-12-12
云服務(wù)器Ubuntu_Server_16.04.1安裝MySQL并開啟遠程連接的方法
這篇文章主要介紹了云服務(wù)器Ubuntu_Server_16.04.1安裝MySQL并開啟遠程連接的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-02-02
mysql如何用sql語句建立學(xué)生課程數(shù)據(jù)庫基本表
這篇文章主要給大家介紹了關(guān)于mysql如何用sql語句建立學(xué)生課程數(shù)據(jù)庫基本表的相關(guān)資料,學(xué)生表是一個常見的數(shù)據(jù)表,用于存儲學(xué)生的個人信息和成績等相關(guān)數(shù)據(jù),文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12

