一條SQL語句葛家,正常執(zhí)行時(shí)候特別快,有時(shí)候會(huì)突然變得特別慢蚀同,而且很難復(fù)現(xiàn)缅刽,它不只是隨機(jī)而且持續(xù)時(shí)間很短。 看上去像數(shù)據(jù)庫抖了一下 – 原因就是MySQL在刷臟頁到磁盤蠢络。
當(dāng)內(nèi)存數(shù)據(jù)頁和磁盤數(shù)據(jù)頁內(nèi)容不一致的時(shí)候拷恨,這個(gè)數(shù)據(jù)頁被稱為“臟頁”。內(nèi)存數(shù)據(jù)寫入磁盤后谢肾,內(nèi)存和磁盤的數(shù)據(jù)頁的內(nèi)容就一致了腕侄,稱為“干凈頁”。 不論臟頁還是干凈頁芦疏,都存在內(nèi)存里冕杠。
觸發(fā)數(shù)據(jù)庫的刷臟頁時(shí)機(jī)
InnoDB的redo log寫滿了。這時(shí)候系統(tǒng)會(huì)停止所有更新操作去刷盤酸茴。這種情況應(yīng)該盡量避免分预,因?yàn)槌霈F(xiàn)這種情況的時(shí)候,整個(gè)系統(tǒng)就不能再接受更新薪捍,所有更新唄堵住笼痹。
內(nèi)存不足。當(dāng)需要新的內(nèi)存頁酪穿,內(nèi)存不夠用的時(shí)候凳干,就要淘汰一些數(shù)據(jù)頁,空出內(nèi)存給別的數(shù)據(jù)頁使用被济。如果淘汰的是“臟頁”救赐,就要將臟頁寫到磁盤。
InnoDB用緩沖池buffer pool來管理內(nèi)存只磷,緩沖池中的內(nèi)存頁有三種狀態(tài):
- 還沒使用
- 使用了并且是干凈頁
- 使用了并且是臟頁
InnoDB的策略是盡量使用內(nèi)存经磅,因此對(duì)于一個(gè)長時(shí)間運(yùn)行的庫來說,未被使用的頁面很少钮追。當(dāng)要讀入的數(shù)據(jù)頁沒有在內(nèi)存的時(shí)候预厌,就必須到緩沖池中申請(qǐng)一個(gè)數(shù)據(jù)頁。這時(shí)候只能把最久不使用的數(shù)據(jù)頁從內(nèi)存中淘汰掉:如果要淘汰的是一個(gè)干凈頁元媚,就直接釋放出來復(fù)用轧叽;當(dāng)如果是臟頁,就必須先講臟頁刷盤惠毁,變成干凈頁后才能復(fù)用犹芹。所以刷臟頁是常態(tài)。
但是出現(xiàn)以下情況會(huì)明顯影響性能:
- 一個(gè)查詢要淘汰的臟頁個(gè)數(shù)太多鞠绰,就會(huì)導(dǎo)致查詢的響應(yīng)事件明顯變長腰埂。
- 日志寫滿,更新全部堵住蜈膨,寫性能跌為0屿笼,這種對(duì)于敏感業(yè)務(wù)來說牺荠,是不能接受的。
- 系統(tǒng)空閑時(shí)候驴一。
- MySQL正常關(guān)閉時(shí)候休雌。
刷盤策略
InnoDB 需要有控制臟頁比例的機(jī)制,來盡量避免性能的影響肝断。
- 設(shè)置InnoDB所在主機(jī)的IO能力杈曲,這樣InnoDB可以獲知全力刷臟頁可以多快。
innodb_io_capacity = IOPS
case: 如果出現(xiàn)MySQL寫入速度很慢胸懈,TPS很低担扑,而數(shù)據(jù)庫主機(jī)IO壓力并不大,很可能就是這個(gè)原因趣钱。
- InnoDB控制引擎按照“全力”的百分比刷臟頁 - 刷盤速度涌献。