1. 結(jié)論:
只要redo log 和 binlog 保證持久化到磁盤(pán),就能確保MySQL異常重啟后,數(shù)據(jù)可以恢復(fù)。
2. 機(jī)制
WAL機(jī)制,(Write Ahead Log): 事務(wù)先寫(xiě)入日志,后持久化到磁盤(pán)。
3. binlog 寫(xiě)入機(jī)制
流程
- 每個(gè)線程內(nèi)都有一個(gè)binlog cache,記錄先寫(xiě)入binlog cache,所有線程共享一個(gè)binlog文件
- binlog cache write into binlog file, binlog file 是存儲(chǔ)在文件操作系統(tǒng)的page cache中。
- binlog file 通過(guò) fsync持久化到磁盤(pán)。
解釋
- write是內(nèi)存之間的操作,速度很快。
- fsync是內(nèi)存和磁盤(pán)之間的操作,速度慢,占據(jù)磁盤(pán)的IOPS。
寫(xiě)入控制策略
write和fsync的時(shí)機(jī)可調(diào),參數(shù)sync_binlog可以控制
- sync_binlog = 0 ,每次提交事務(wù)只write, 不fsync.
- sync_binlog = 1, 每次提交事務(wù)都會(huì)執(zhí)行fsync。
- sync_binlog= N, 每次提交事務(wù)都write, 但累積N個(gè)事務(wù)后才fsync,N 的取值范圍為(100,1000)。
通俗理解,sync_binlog 控制的是fsync的時(shí)機(jī),處于數(shù)據(jù)恢復(fù)和效率,一般不取0和1,
4. redo log 寫(xiě)入機(jī)制
流程
- redo log 先寫(xiě)入 redo log buffer中,存儲(chǔ)在mysql的進(jìn)程中。(內(nèi)存)
- 寫(xiě)到(write)page cache, 存儲(chǔ)在文件系統(tǒng)的頁(yè)緩存中。(內(nèi)存)
- 持久化(fsync)到磁盤(pán)。
寫(xiě)入控制策略
redo log的寫(xiě)入控制同樣是通過(guò)參數(shù)去調(diào)整:innodb_flush_log_at_trx_commit
從參數(shù)名就可以看出, 是innodb提供的在事務(wù)提交時(shí)redo_log的刷盤(pán)策略
- 設(shè)置為0表示 每次事務(wù)提交時(shí)都把redo log留在 redo log buffer。
- 設(shè)置為1表示 每次事務(wù)提交時(shí)都將 redo log 直接持久化到磁盤(pán)中。
- 設(shè)置為2表示 每次事務(wù)提交時(shí)都只是把redo log 寫(xiě)到page cache。
此外,Innodb存在一個(gè)后臺(tái)線程,每隔1秒,機(jī)會(huì)將redo lo個(gè)buffer中的日志,刷盤(pán)到page cache,然后持久化到磁盤(pán)中。
5. 兩階段提交機(jī)制
MySQL一般采用的是雙“1”策略,就是sync_binlog 和 innodb_flush_log_at_trx_commit都為1。
換言之,一次完整的事務(wù)提交需要等待兩次刷盤(pán),一次是在redo log(prepare) fsync,一次是在寫(xiě)binlog中fsync。
引發(fā)新的問(wèn)題:
如果MySQL的TPS為每秒2萬(wàn),按照兩階段提交,每秒機(jī)會(huì)有四萬(wàn)次寫(xiě)磁盤(pán),但是
磁盤(pán)能力就2萬(wàn)每秒,如何實(shí)現(xiàn)兩萬(wàn)的TPS?
換言之:就是在遇到磁盤(pán)瓶頸時(shí),如何優(yōu)化,減少刷盤(pán)次數(shù)
組提交機(jī)制(group commit)
LSN
在介紹組提交之前,需要了解日志邏輯序列號(hào)(log sequence number, LSN),這是一個(gè)單調(diào)遞增,且對(duì)應(yīng)redo log的寫(xiě)入點(diǎn),每次寫(xiě)入長(zhǎng)度為length的redo log, LSN的值就會(huì)加上length。
這段話比較難理解,可以看圖理解。
redo log 采用組提交的示例
圖片來(lái)自《MySQL45講》
- trx1 是第一個(gè)到達(dá)的,會(huì)被選為這組的 leader;
- 等 trx1 要開(kāi)始寫(xiě)盤(pán)的時(shí)候,這個(gè)組里面已經(jīng)有了三個(gè)事務(wù),這時(shí)候 LSN 也變成了 160;
- trx1 去寫(xiě)盤(pán)的時(shí)候,帶的就是 LSN=160,因此等 trx1 返回時(shí),所有 LSN 小于等于 160 的 redo log,都已經(jīng)被持久化到磁盤(pán);
- 這時(shí)候 trx2 和 trx3 就可以直接返回。
總結(jié):一次組提交里面,組員越多,節(jié)約磁盤(pán) IOPS 的效果越好。
在并發(fā)場(chǎng)景下,為了盡可能多的的在一次組提交內(nèi)包含更多的組員,第一個(gè)事務(wù)在寫(xiě)完redo log buffer之后,接下來(lái)的fsync需要盡可能的晚調(diào)用。
優(yōu)化
在MySQL 中就有這樣的優(yōu)化:為了讓一次fsync帶的組員更多,采取拖時(shí)間。
將redo log prepare分成兩個(gè)階段文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-484957.html
- write: 將redolog cache 寫(xiě)入 page cache
- fsync:: 將page cache中的redo log 日志持久化到磁盤(pán)中。
將binlog 分成兩個(gè)階段: - write : 將日志從binlog cache寫(xiě)入page cache中的binlog文件
- fsync: 將binlog文件持久化到磁盤(pán)。
本著拖時(shí)間的原則來(lái)分析:
將 prepare 階段的 fsync 拖到binlog的write之后,
同樣binlog的fsync 拖到了 redo log的fsync之后,
優(yōu)化后的方案:redo log 和bin log 都實(shí)現(xiàn)了組提交。
區(qū)別在于 binlog的組提交帶來(lái)的優(yōu)化效果不如 redo log,主要原因是拖的時(shí)間不長(zhǎng)
大佬原話:
但是可以通過(guò)參數(shù)來(lái)控制:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-484957.html
- binlog_group_commit_sync_delay ;表示延遲多少微秒后才調(diào)用 fsync;
-
binlog_group_commit_sync_no_delay_count ,表示累積多少次以后才調(diào)用 fsync。
兩條件是或的關(guān)系,滿足一個(gè)就會(huì)調(diào)用fsync。
到了這里,關(guān)于MySQL如何保證數(shù)據(jù)的可靠性(保證數(shù)據(jù)不丟失)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!