前段時(shí)間看了下姜老師寫的一個(gè)相關(guān)文章P8級(jí)面試難題,after_sync vs after_commit,哪個(gè)性能更好
寫的特別詳細(xì),很有收獲,這里結(jié)合一些之前看到的其他介紹,簡單的匯總整理下.
首先了解下兩個(gè)參數(shù)的區(qū)別
after_commit在主機(jī)事務(wù)提交后將日志傳送到從機(jī),after_sync是先傳再提交。

上圖文字說明可能大家感覺不是太直觀具體,如果在源碼層區(qū)分估計(jì)理解更加深些,參考[MySQL層事務(wù)提交流程簡析](https://mp.weixin.qq.com/s/4Plg7Bc1KDuhKD5fqx6NSA

從圖中可以看出在設(shè)置為after_sync時(shí),則在第21步后確認(rèn),after_commit則在24步后確認(rèn).
可以看出after_commit如果在主庫掛的時(shí)候,可能會(huì)導(dǎo)致數(shù)據(jù)丟失,而after_sync則不會(huì)丟失數(shù)據(jù),但是可能在主庫正要返回提交成功給客戶端的時(shí)間點(diǎn)掛掉則會(huì)導(dǎo)致用戶以為沒有寫入成功,但是從庫已經(jīng)存在數(shù)據(jù)的情況.
因此如果業(yè)務(wù)無法接受數(shù)據(jù)丟失的話推薦使用after_sync.
性能對(duì)比(來自姜老師分享文章)
一個(gè)事務(wù)在半同步模式下提交,無論是after_sync還是after_commit,都要經(jīng)歷4個(gè)階段:
- InnoDB Redo File Write
- binlog File Flush & Sync
- InnoDB Redo File Commit(同時(shí)釋放事務(wù)持有的鎖)
- Send binlog to Slave
after_sync模式下,4個(gè)階段的順序?yàn)?->2->4->3,after_commit模式為1->2->3->4。這個(gè)順序也解釋了為什么after_commit為什么會(huì)有“幻讀”問題。
現(xiàn)在假設(shè)階段1、2、3各需要1ms時(shí)間,階段4需要0.2ms時(shí)間,那么一次事務(wù)提交的時(shí)間:
T after_sync = 1 + 1 + 0.2 + 1 = 3.2 ms
T after_commit = 1 + 1 + 0.2 + 1 = 3.2 ms
以下分單線程,多線程對(duì)比下執(zhí)行時(shí)間
單線程情況下
-
after_sync 提交流程
image.png -
after_commit 提交流程
image.png
可見單線程下after_commit性能較佳(如果主從不在相同機(jī)房,時(shí)間較長時(shí),after_commit理論上會(huì)比after_sync單線程性能強(qiáng)很多)
多線程
在并發(fā)的場景下,若事務(wù)之間的修改不沖突,則事務(wù)是可以同時(shí)提交的,也就是可以進(jìn)入到組提交(Group Commit)優(yōu)化流程中。那么這時(shí),事務(wù)的提交變?yōu)榱耍?/p>

事務(wù)TX1~TX4可以同時(shí)進(jìn)入到提交階段,這時(shí)會(huì)進(jìn)入到MySQL的組提交優(yōu)化中。這時(shí)產(chǎn)生的優(yōu)化效果有:
InnoDB Redo Prepare只需要一次I/O操作
InnoDB binlog Write只需要一次I/O操作
接收到ACK后喚醒事務(wù)提交隊(duì)列只需要一次
可以看到有組提交加持下數(shù)據(jù)庫的的性能提升是非常明顯的,假設(shè)沒有組提交,并且喚醒等待線程需要0.02ms,則沒有組提交的情況下,TX1~TX4事務(wù)所需要的時(shí)間為:
T[1~4 ]= ( 1 + 1 + 1 + 0.2 + 0.02 ) * 4 = 12.88 ms
在有組提交的優(yōu)化加持下,TX1~TX4事務(wù)所需要的時(shí)間優(yōu)化為了:
T[1~4] = 1 + 1 + 1 + 0.2 + 0.02 = 3.22 ms

