《MySQL——redo log 与 binlog 写入机制》
目錄
- binlog寫(xiě)入機(jī)制
- redo log寫(xiě)入機(jī)制
- 組提交機(jī)制實(shí)現(xiàn)大量的TPS
- 理解WAL機(jī)制
- 如何提升IO性能瓶頸
WAL機(jī)制告訴我們:只要redo log與binlog保證持久化到磁盤(pán)里,就能確保MySQL異常重啟后,數(shù)據(jù)可以恢復(fù)。
下面主要記錄一下MySQL寫(xiě)入binlog和redo log的流程。
binlog寫(xiě)入機(jī)制
1、事務(wù)執(zhí)行過(guò)程中,先把日志寫(xiě)到binlog cache,事務(wù)提交的時(shí)候,再把binlog cache寫(xiě)到binlog文件中。
2、binlog cache,系統(tǒng)為每個(gè)線程分配了一片binlog cache內(nèi)存,參數(shù)binlog_cache_size控制單個(gè)線程內(nèi)binlog cache大小。如果超過(guò)了這個(gè)大小就要暫存磁盤(pán)
3、事務(wù)提交的時(shí)候,執(zhí)行器把binlog cache里完整的事務(wù)寫(xiě)入binlog中。并清空binlog cache
4、每個(gè)線程都有自己的binlog cache,共用一份binlog文件
5、write,是把日志寫(xiě)入到文件系統(tǒng)的page cache,內(nèi)存中,沒(méi)有持久化到磁盤(pán),所以速度比較快,圖中的fsync是將數(shù)據(jù)持久化到磁盤(pán),占用磁盤(pán)的IOPS
關(guān)于何時(shí)write、fsync是由參數(shù)sync_binlog控制的:
1、sync_binlog = 0時(shí),每次提交事務(wù)都只write,不fsync; 2、sync_binlog = 1時(shí),每次提交事務(wù)都會(huì)執(zhí)行fsync; 3、sync_binlog = N(N>1)時(shí),表示每次提交事務(wù)都write,但累積N個(gè)事務(wù)后才fsync。sync_binlog控制binlog真正刷盤(pán)的頻率,對(duì)于一個(gè)IO非常大的情景,這個(gè)數(shù)字調(diào)大可以提高性能,但是如果容錯(cuò)率非常低的情況下,必須設(shè)為1.(sync_binlog設(shè)置為N對(duì)應(yīng)的風(fēng)險(xiǎn)是:如果主機(jī)發(fā)生異常重啟,會(huì)丟失最近N個(gè)事務(wù)的binlog日志)
redo log寫(xiě)入機(jī)制
事務(wù)在執(zhí)行過(guò)程中,生成的redo log是要先寫(xiě)到redo log buffer的。
redo log buffer里面的內(nèi)容并不需要每次生成后都要持久化到磁盤(pán)中。
如果事務(wù)執(zhí)行期間MySQL發(fā)生異常重啟,那么這部分日志就丟了。由于事務(wù)并沒(méi)有提交,所以這時(shí)日志丟了也不會(huì)有損失。
事務(wù)沒(méi)提交的時(shí)候,redo log buffer部分日志也是有可能被持久化到磁盤(pán)中的。
上面三個(gè)顏色表征了redo log可能的三種狀態(tài):
1、存在redo log buffer中,物理上是在MySQL進(jìn)程內(nèi)存中,即紅色部分;
2、寫(xiě)到磁盤(pán)(write),但是沒(méi)有持久化(fsync),物理上實(shí)在文件系統(tǒng)的page cache里面,即黃色部分;
3、持久化到磁盤(pán),對(duì)應(yīng)的是hard disk,也就是圖中的綠色部分;
前兩步是寫(xiě)內(nèi)存,最后一步是磁盤(pán)IO,所以要在page cache夠大且不影響寫(xiě)入page cache前將redo log 持久化到磁盤(pán) 。
為了控制redo log 的寫(xiě)入策略,InnoDB提供了innodb_flush_log_at_trx_commit參數(shù),他有三種可能取值:
1、設(shè)置為0,每次事務(wù)提交的時(shí)候都只是把redo log留在redo log buffer中; 2、設(shè)置為1,每次事務(wù)提交的時(shí)候都只是把redo log直接持久化到磁盤(pán); 3、設(shè)置為2,每次事務(wù)提交時(shí)都只是把redo log寫(xiě)到page cache;與binlog不同,binlog是每個(gè)線程都有一個(gè)binlog cache,而redo log是多個(gè)線程共用一個(gè)redo log buffer。
InnoDB有一個(gè)后臺(tái)線程,每隔1s,就會(huì)把redo log buffer中的日志,調(diào)用write寫(xiě)到文件系統(tǒng)的page cache,然后調(diào)用fsync持久化到磁盤(pán),事務(wù)執(zhí)行過(guò)程中的redo log也是直接寫(xiě)在redo log buffer上的,所以,未提交的事務(wù)的redolog也可能被持久化到磁盤(pán)。
還有兩種場(chǎng)景也會(huì)導(dǎo)致沒(méi)有提交的事務(wù)的redo log寫(xiě)入到磁盤(pán)中:
情形1:
redo log buffer占用的空間即將達(dá)到innodb_log_buffer_size一半的時(shí)候,后臺(tái)線程會(huì)主動(dòng)寫(xiě)盤(pán)。
(這里只是write,沒(méi)有fsync)
情形2:
并行的事務(wù)提交的時(shí)候,順帶將這個(gè)事務(wù)的redo log buffer持久化到磁盤(pán)。
(事務(wù)A執(zhí)行一半,部分redo log到buffer中;事務(wù)B提交,且 innodb_flush_log_at_trx_commit ,會(huì)把redo log buffer里的log全部持久化到磁盤(pán)中)
補(bǔ)充說(shuō)明
兩階段提交在時(shí)序上redo log先prepare 再寫(xiě)binlog,最后再把redo log commit;
innodb_flush_log_at_trx_commit 設(shè)置成 1,prepare階段redo log就已經(jīng)落盤(pán)。所以redo log再commit的時(shí)候就不需要fsync了,只會(huì)write到文件系統(tǒng)的page cache中就夠了。
sync_binlog 和 innodb_flush_log_at_trx_commit都設(shè)置為1,即一個(gè)事務(wù)完整提交前,需要等待兩次刷盤(pán),一次是redo log(prepare階段),一次是binlog。
組提交機(jī)制實(shí)現(xiàn)大量的TPS
首先介紹日志邏輯序列號(hào)(log sequence number,LSN)的概念。LSN是單調(diào)遞增的,每次寫(xiě)入長(zhǎng)度length的redo log,LSN的值就會(huì)加上length。
三個(gè)并發(fā)事務(wù)(trx1,trx2,trx3)在prepare階段,都寫(xiě)完redo buffer,并持久化到磁盤(pán)。
對(duì)應(yīng)的LSN為50、120、160.
對(duì)應(yīng)流程:
1、trx1第一個(gè)到達(dá),被選為這組的leader;
2、等trx1要開(kāi)始寫(xiě)盤(pán)的時(shí)候,這個(gè)組里面已經(jīng)有三個(gè)事務(wù),這時(shí)候LSN也變成了160;
3、trx1去寫(xiě)盤(pán)的時(shí)候,LSN=160;trx1返回時(shí),所有LSN<= 160的redo log都被持久化到磁盤(pán)中;
4、trx2與trx3直接返回。
總結(jié):
一次組提交中,組員越多,節(jié)約磁盤(pán)IOPS的效果越好。如果是單線程,就只能一個(gè)事務(wù)對(duì)應(yīng)一次持久化操作
| 兩階段提交 | 兩階段提交細(xì)化 |
這樣保證binlog也可以組提交了。由于step3速度快,所以集合到一起的binlog比較少,所以binlog的組提交效果不如redo log組提交。
提升binlog效果:
--1.binlog_group_commit_sync_delay :b表示延遲多少微秒后才調(diào)用fsync; --2.binlog_group_commit_sync_no_delay_count :表示累積多少次以后才調(diào)用fsync;理解WAL機(jī)制
WAL機(jī)制是減少磁盤(pán)寫(xiě),可是每次提交事務(wù)都要寫(xiě)redo log和binlog ,磁盤(pán)讀寫(xiě)次數(shù)沒(méi)有變少。
所以WAL機(jī)制主要得益于兩個(gè)方面:
--1、redo log和binlog都是順序?qū)?#xff0c;磁盤(pán)的順序?qū)懕入S機(jī)寫(xiě)速度要快 --2、組提交機(jī)制,可以降低磁盤(pán)IOPS消耗如何提升IO性能瓶頸
1、設(shè)置binlog_group_commit_sync_delay和binlog_group_commit_sync_no_delay_count參數(shù),減少binlog的寫(xiě)盤(pán)次數(shù)。這個(gè)方法是基于“額外故意等待”來(lái)實(shí)現(xiàn)的,可能會(huì)增加語(yǔ)句的響應(yīng)時(shí)間,但是不會(huì)丟失數(shù)據(jù)
2、將sync_binlog設(shè)置為大于1的值(100~1000)。不過(guò)會(huì)有主機(jī)掉電時(shí)丟binlog日志的風(fēng)險(xiǎn)
3、將 innodb_flush_log_at_trx_commit 設(shè)置為2。會(huì)有主機(jī)掉電丟數(shù)據(jù)的風(fēng)險(xiǎn)
總結(jié)
以上是生活随笔為你收集整理的《MySQL——redo log 与 binlog 写入机制》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 杜卡迪大魔鬼多少钱啊?
- 下一篇: 《MySQL——主备一致性六问六答》