一顷蟀、binlog的寫入機(jī)制
- binlog寫入邏輯:
- 事務(wù)執(zhí)行過(guò)程中、先寫日志導(dǎo)binlog cache囤萤、事務(wù)提交時(shí)、再把binlog cache寫入到binlog文件中.
- 一個(gè)事務(wù)的binlog不能被拆開富雅、因此不論事務(wù)有多大滚婉、也要確保一次性寫入. 系統(tǒng)給binlog cache每個(gè)線程分配一片內(nèi)存(binlog_cache_size大小), 超過(guò)會(huì)先暫存到磁盤.
- 事務(wù)提交時(shí)、執(zhí)行器會(huì)把binlog cache里的完整事務(wù)寫入binlog锥余、清空binlog cache.
- 每個(gè)線程有自己的binlog cache、但共用binlog文件.
事務(wù)提交、先寫入到文件系統(tǒng)的page cache(write), 然后調(diào)用fsync寫入磁盤(占用IOPS)
write和fsync的時(shí)機(jī):
sync_binlog=0, 每次事務(wù)提交只write蔬将、不fsync
sync_binlog=1, 每次事務(wù)提交都執(zhí)行fsync
sync_binlog=N, 每次事務(wù)提交都write莉给、累積N個(gè)事務(wù)才fsync
所以、在出現(xiàn)IO瓶頸的場(chǎng)景里丧蘸、可以將sync_binlog設(shè)置為一個(gè)比較大的值演训、可以提升性能.
風(fēng)險(xiǎn): 若主機(jī)異常重啟庭猩、會(huì)丟失最近N個(gè)事務(wù)的binlog.
二、redo log的寫入機(jī)制
事務(wù)執(zhí)行過(guò)程中會(huì)先寫redo log buffer, 然后才寫redo log
從redo log的三種狀態(tài)說(shuō)起:
- 存在redo log buffer中、物理上是在 mysql 進(jìn)程內(nèi)存中.
- 寫到磁盤write、但未持久化fsync蠢护、物理上是在文件系統(tǒng)的Page Cache中
- 持久化到磁盤
1单寂、2的過(guò)程都很快、但3的速度就慢很多了. InnoDB提供了三種策略, 通過(guò) innodb_flush_log_at_trx_commit參數(shù)控制:
- 0, 表示每次事務(wù)提交只把redo log留在redo log buffer中
- 1, 表示每次事務(wù)提交都將redo log直接持久化到磁盤
- 2, 表示每次事務(wù)提交都把redo log寫到Page Cache.
InnoDB 有一個(gè)后臺(tái)線程贤惯、每隔1s屁商、會(huì)把redo log buffer中的日志調(diào)用write寫到FS Pae Cache官还、然后調(diào)用 fsync 持久化到磁盤.
注意: 事務(wù)執(zhí)行過(guò)程中的redo log也是在buffer中、可能會(huì)被后臺(tái)線程一起持久化到磁盤
還有兩種場(chǎng)景會(huì)將一個(gè)未提交的事務(wù)redo log寫入磁盤:
- redo log buffer占用的空間即將達(dá)到innodb_log_buffer_size 一半的時(shí)候、后臺(tái)線程會(huì)主動(dòng)寫盤. (此時(shí)事務(wù)未提交、只是write、并未fsync, 即: 只留在FS Page Cache)
- 并行事務(wù)提交時(shí), 順帶將該事務(wù)的 redo log buffer持久化到磁盤、eg. Trx A執(zhí)行到一半、Trx B要把buffer數(shù)據(jù)寫入磁盤、會(huì)順帶把Trx A的日志一起持久化到磁盤
注意: 若將 innodb_flush_log_at_trx_commit 設(shè)為1, redo log在prepare階段就要持久化一次、因?yàn)橛幸粋€(gè)崩潰恢復(fù)依賴于prepare的redo log + binlog.
通常說(shuō)的雙1
配置堰塌、是redo log 和binlog的刷盤機(jī)制都設(shè)為1, 即: 一個(gè)事務(wù)完整提交前、需要等待兩次刷盤: redo log(prepare階段) 和 binlog
思考: TPS 2w/s 的話、寫盤就是 4w/s, 但磁盤能力只有2w/s, 是怎么實(shí)現(xiàn)的呢 ?
組提交: 三個(gè)并發(fā)事務(wù)trx1, trx2, trx3, 對(duì)應(yīng)LSN(日志邏輯序列化、單調(diào)遞增)分別為:50, 120, 160, trx1寫盤時(shí)、這組(trx1->3)已經(jīng)有3個(gè)事務(wù)、LSN也變成了160, 去寫盤時(shí)、帶的LSN=160, 等trx1返回時(shí)、所有LSN<160的redo log都已持久化到磁盤, trx2,trx3可直接返回.
在并發(fā)更新場(chǎng)景下柑蛇、第一個(gè)事務(wù)寫完 redo log buffer粘我、調(diào)用fsync越晚娇豫、組員越多浦楣、節(jié)約IOPS效果越好.
binlog的write 和 fsync的時(shí)間間隔短历恐、組提交優(yōu)化不如redo log.
可以通過(guò)設(shè)置以下參數(shù)來(lái)提升效果:
- binlog_group_commit_sync_delay, 延遲x 微秒后才調(diào)用fsync
- binlog_group_commit_sync_no_delay_count, 累積x次以后調(diào)用fsync
二者滿足其一就調(diào)用 fsync
另: 不建議設(shè)置 innodb_flush_log_at_trx_commit=0, 因?yàn)檫@樣redo log只保存在內(nèi)存中溪烤、MySQL異常重啟會(huì)丟失數(shù)據(jù)枪眉、風(fēng)險(xiǎn)太大. 而redo log寫到 FS Page Cache的速度也是很快的蒿秦、不會(huì)損失很多性能, 可以保證異常重啟不丟數(shù)據(jù)渡处、風(fēng)險(xiǎn)小很多.