前言
上一篇文章我們首次提到Redo Log的概念,Redo Log是數(shù)據(jù)庫體系架構(gòu)中非常重要的一個模塊,它能保證數(shù)據(jù)庫的Crash-safe(崩潰恢復(fù))的能力。而今天要介紹的Log Buffer正和Redo Log息息相關(guān)、密不可分。所以我們就來一起來了解它。
官檔地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-redo-log-buffer.html
點(diǎn)擊此處跳轉(zhuǎn)
一、Redo Log是什么
Redo Log(重做日志)是MySQL中非常重要的日志模塊
MySQL官方給出的解釋是:日志緩沖區(qū)是存儲要寫入磁盤上的日志文件的數(shù)據(jù)的內(nèi)存區(qū)域,日志緩沖區(qū)的內(nèi)容定期刷新到磁盤。
重做日志是一種基于磁盤的數(shù)據(jù)結(jié)構(gòu),用于在崩潰恢復(fù)期間糾正不完整事務(wù)寫入的數(shù)據(jù)。在正常操作期間,重做日志對由SQL語句或低級API調(diào)用產(chǎn)生的更改表數(shù)據(jù)的請求進(jìn)行編碼。在初始化期間和接受連接之前,會自動重播在意外關(guān)閉之前未完成更新數(shù)據(jù)文件的修改,MySQL里經(jīng)常說到的WAL技術(shù)(WAL的全稱是Write-Ahead Logging),它的關(guān)鍵點(diǎn)就是日志先行(也稱為寫前日志,實(shí)際寫數(shù)據(jù)之前,先把修改的數(shù)據(jù)記錄到日志文之間中。即先寫日志,再寫磁盤),其實(shí)很多數(shù)據(jù)庫軟件設(shè)計的理念都是日志先行。MySQL中日志先行的這個“日志”就是Redo Log。
Redo Log是InnoDB引擎特有的日志,正是因?yàn)橛辛薘edo Log,才保證了InnoDB存儲引擎的Crash-safe能力。
Redo Log是物理日志,記錄的是“在某個數(shù)據(jù)頁上做了什么修改(做了什么改動)”。一句話概括一下:Redo Log是為了保證已提交事務(wù)的ACID特性,同時能夠提高數(shù)據(jù)庫性能的技術(shù)
。
二、Redo Log三層架構(gòu)
簡單來說一下Redo Log的三層結(jié)構(gòu):
- 粉色部分:是InnoDB一項(xiàng)很重要的內(nèi)存結(jié)構(gòu)(In-Memory Structure),即我們的Log Buffer(日志緩沖區(qū)),這一層,是MySQL應(yīng)用程序用戶態(tài)控制。
- 黃色部分:操作系統(tǒng)文件系統(tǒng)的緩沖區(qū)(FS Page Cache),這一層,是操作系統(tǒng)OS內(nèi)核態(tài)控制。
- 綠色部分:就是落盤的物理日志文件。
2.1 Redo Log最終落盤的步驟
- 首先,事務(wù)提交的時候,會寫入Log Buffer,這里調(diào)用的是MySQL自己的函數(shù)
WriteRedoLog
; - 接著,只有當(dāng)MySQL發(fā)起系統(tǒng)調(diào)用寫文件write時,Log Buffer里的數(shù)據(jù),才會寫到FS Page Cache。注意,MySQL系統(tǒng)調(diào)用完write之后,就認(rèn)為文件已經(jīng)寫完,如果不flush,什么時候落盤,是操作系統(tǒng)決定的;
- 最后,由操作系統(tǒng)(當(dāng)然,MySQL也可以主動flush)將FS Page Cache里的數(shù)據(jù),最終fsync到磁盤上;
操作系統(tǒng)為什么要緩沖數(shù)據(jù)到FS Page Cache里,而不直接刷盤呢?
這里就是將“每次寫”優(yōu)化為“批量寫”,以提高操作系統(tǒng)性能。
數(shù)據(jù)庫為什么要緩沖數(shù)據(jù)到Log Buffer里,而不是直接write呢?
這也是“每次寫”優(yōu)化為“批量寫”思路的體現(xiàn),以提高數(shù)據(jù)庫性能。
Redo Log三層架構(gòu),MySQL做了一次批量寫優(yōu)化,OS做了一次批量寫優(yōu)化,確實(shí)能極大提升性能,但有什么副作用嗎?
有優(yōu)點(diǎn),必有缺點(diǎn)。這個副作用,就是可能丟失數(shù)據(jù):
事務(wù)提交時,將Redo Log寫入Log Buffer,就會認(rèn)為事務(wù)提交成功
如果寫入Log Buffer的數(shù)據(jù),write入FS Page Cache之前,數(shù)據(jù)庫崩潰,就會出現(xiàn)數(shù)據(jù)丟失
如果寫入FS Page Cache的數(shù)據(jù),fsync入磁盤之前,操作系統(tǒng)奔潰,也可能出現(xiàn)數(shù)據(jù)丟失;
如上文所說,應(yīng)用程序系統(tǒng)調(diào)用完write之后(不可能每次write后都立刻flush,這樣寫日志很蠢),就認(rèn)為寫成功了,操作系統(tǒng)何時fsync,應(yīng)用程序并不知道,如果操作系統(tǒng)崩潰,數(shù)據(jù)可能丟失)
2.2 MySQL對上述可能存在問題的折衷方案
參數(shù)innodb_flush_log_at_trx_commit
能夠控制事務(wù)提交時,刷Redo Log的策略,目前有三種策略,即對應(yīng)可設(shè)置的值可以是0、1或2。
-
策略一:最佳性能(innodb_flush_log_at_trx_commit=0)
處理過程: 每隔一秒,才將Log Buffer中的數(shù)據(jù)批量write入FS Page Cache,同時MySQL主動fsync。
缺點(diǎn): 這種策略,如果數(shù)據(jù)庫奔潰,有一秒的數(shù)據(jù)丟失。 -
策略二:強(qiáng)一致(innodb_flush_log_at_trx_commit=1)
處理過程: 每次事務(wù)提交,都將Log Buffer中的數(shù)據(jù)write入FS Page Cache,同時MySQL主動fsync。這種策略,是InnoDB的默認(rèn)配置,為的是保證事務(wù)ACID特性。
缺點(diǎn): 這種策略,性能較其余兩種策略較差。 -
策略三:折衷(innodb_flush_log_at_trx_commit=2)
處理過程: 每次事務(wù)提交,都將Log Buffer中的數(shù)據(jù)write入FS Page Cache;每隔一秒,MySQL主動將FS Page Cache中的數(shù)據(jù)批量fsync。
缺點(diǎn): 這種策略,如果操作系統(tǒng)奔潰,最多有一秒的數(shù)據(jù)丟失。(因?yàn)镺S也會fsync,MySQL主動fsync的周期是一秒,所以最多丟一秒數(shù)據(jù)。磁盤IO次數(shù)不確定,因?yàn)椴僮飨到y(tǒng)的fsync頻率并不是MySQL能控制的)
2.3 Redo Log刷盤策略最佳實(shí)踐
高并發(fā)業(yè)務(wù),行業(yè)最佳實(shí)踐,是使用第三種折衷配置(innodb_flush_log_at_trx_commit=2),這是因?yàn)椋?/p>
-
配置為2和配置為0,性能差異并不大,因?yàn)閷?shù)據(jù)從Log Buffer拷貝到FS Page Cache,雖然跨越用戶態(tài)與內(nèi)核態(tài),但畢竟只是內(nèi)存的數(shù)據(jù)拷貝,速度很快;
-
配置為2和配置為0,安全性差異巨大,操作系統(tǒng)崩潰的概率相比MySQL應(yīng)用程序崩潰的概率,小很多,設(shè)置為2,只要操作系統(tǒng)不奔潰,也絕對不會丟數(shù)據(jù)。
三 、Redo Log相關(guān)參數(shù)
mysql> show variables like '%innodb_log%';
+------------------------------------+----------+
| Variable_name | Value |
+------------------------------------+----------+
| innodb_log_buffer_size | 16777216 |
| innodb_log_checksums | ON |
| innodb_log_compressed_pages | ON |
| innodb_log_file_size | 50331648 |
| innodb_log_files_in_group | 2 |
| innodb_log_group_home_dir | ./ |
| innodb_log_spin_cpu_abs_lwm | 80 |
| innodb_log_spin_cpu_pct_hwm | 50 |
| innodb_log_wait_for_flush_spin_hwm | 400 |
| innodb_log_write_ahead_size | 8192 |
| innodb_log_writer_threads | ON |
+------------------------------------+----------+
11 rows in set (0.01 sec)
mysql> show variables like '%innodb_flush_log%';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_timeout | 1 |
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
2 rows in set (0.00 sec)
從上面可以看出,Redo Log的相關(guān)參數(shù)還是很多的,所以我們拿重點(diǎn)的來說,其余參數(shù)一般為默認(rèn)值,感興趣的可移步MySQL官檔(https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html)進(jìn)行查閱
2.1 innodb_log_buffer_size
InnoDB用于寫入磁盤上的日志文件的緩沖區(qū)的大小(以字節(jié)為單位)。這就是定義我們文章標(biāo)題的Log Buffer大小的參數(shù)。隨著32KB和64KBinnodb_page_size值的引入,默認(rèn)值從8MB更改為16MB。大型日志緩沖區(qū)使大型事務(wù)能夠運(yùn)行,而無需在事務(wù)提交之前將日志寫入磁盤。因此,如果您有更新、插入或刪除許多行的事務(wù),則增大日志緩沖區(qū)可以節(jié)省磁盤 I/O。
set persist innodb_log_buffer_size =33554432;
2.2 innodb_log_checksums
啟用或禁用重做日志頁面的校驗(yàn)和,當(dāng)innodb_log_checksums被禁用時,重做日志頁面校驗(yàn)字段的內(nèi)容被忽略,默認(rèn)是開啟
set persist innodb_log_checksums = on;
2.3 innodb_log_compressed_pages
日志文件頁存儲壓縮 , 將減少redo log的寫入量。默認(rèn)是開啟
set persist innodb_log_compressed_pages= on;
2.4 innodb_log_file_size & innodb_log_files_in_group
innodb_log_file_size
是日志組每個Redo Log文件的大小,單位字節(jié)innodb_log_files_in_group
是定義日志組文件的數(shù)量
innodb_log_file_size * innodb_log_files_in_group 組合大小不能超過略小于 512GB 的最大值。從文章開頭的架構(gòu)圖可以看出,Log Buffer也是內(nèi)存+磁盤的結(jié)構(gòu),這兩個參數(shù)就是定義Log Buffer磁盤結(jié)構(gòu)日志文件組的,同時這兩個參數(shù)也很重要。
write pos
是當(dāng)前記錄的位置,一邊寫一邊后移,寫到第2號文件末尾后就回到0號文件開頭。checkpoint
是當(dāng)前要擦除的位置,也是往后推移并且循環(huán)的,擦除記錄前要把記錄更新到數(shù)據(jù)文件。write pos和checkpoint之間的“Free
”部分還空著的部分,可以用來記錄新的操作。如果write pos追上checkpoint,表示Redo Log滿了,這時候不能再執(zhí)行新的更新,得停下來把checkpoint推進(jìn)一下
2.5 innodb_flush_log_at_trx_commit
控制提交操作的嚴(yán)格ACID合規(guī)性與當(dāng)與提交相關(guān)的I/O操作重新排列并批量完成時可能實(shí)現(xiàn)的更高性能之間的平衡。這個參數(shù)非常重要,后面的Log Buffer原理主要是關(guān)于這個參數(shù)的。設(shè)置的值不同會產(chǎn)生不同的效果,可設(shè)置的值可以是0、1或2。
- 1:表示每次事務(wù)提交都會將redo log buffer刷寫到redo log
- 0:表示每次事務(wù)提交不會刷寫到redo log,而是一秒后再刷寫到redo log
- 2:表示每次事務(wù)提交不會刷寫到redo log,而是存放到os cache,等一秒后再刷寫到redo log
今天主要講解了Redo Log和MySQL InnoDB Log Buffer的工作原理,通過流程圖的方式來說明Redo Log三種刷盤策略的工作流程,偏理論的知識,內(nèi)容比較少也很好理解,大家理解記憶即可
至此今天的學(xué)習(xí)就到此結(jié)束了,愿您成為堅不可摧的自己~~~
?
You can’t connect the dots looking forward; you can only connect them looking backwards. So you have to trust that the dots will somehow connect in your future.You have to trust in something - your gut, destiny, life, karma, whatever. This approach has never let me down, and it has made all the difference in my life
如果我的內(nèi)容對你有幫助,請 點(diǎn)贊
、評論
、收藏
,創(chuàng)作不易,大家的支持就是我堅持下去的動力文章來源:http://www.zghlxwxcb.cn/news/detail-434297.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-434297.html
到了這里,關(guān)于MySQL之Log Buffer詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!