概念:
臟頁:
當(dāng)內(nèi)存數(shù)據(jù)頁跟磁盤數(shù)據(jù)頁不一致時,稱為內(nèi)存頁的“臟頁”。
干凈頁:
內(nèi)存數(shù)據(jù)寫入磁盤后巴粪,內(nèi)存和磁盤上的數(shù)據(jù)頁內(nèi)容就一致了,稱為“干凈頁”。
在寫內(nèi)存和日志肛根,而MySQL偶爾抖一下的瞬間辫塌,可能就是在刷臟頁(flush)。
什么情況會引發(fā)數(shù)據(jù)庫的 flush 過程呢派哲?
1.?臼氨,對應(yīng)的就是 InnoDB 的 redo log 寫滿了。這時候系統(tǒng)會停止所有更新操作芭届,把 checkpoint 往前推進(jìn)储矩,redo log 留出空間可以繼續(xù)寫。留出來的空間對應(yīng)的臟頁都flush到磁盤中褂乍。
2. 對應(yīng)的就是系統(tǒng)內(nèi)存不足持隧。當(dāng)需要新的內(nèi)存頁,而內(nèi)存不夠用的時候逃片,就要淘汰一些數(shù)據(jù)頁屡拨,空出內(nèi)存給別的數(shù)據(jù)頁使用。如果淘汰的是“臟頁”褥实,就要先將臟頁寫到磁盤呀狼。
3.?對應(yīng)的就是 MySQL 認(rèn)為系統(tǒng)“空閑”的時候。
4.?對應(yīng)的就是 MySQL 正常關(guān)閉的情況损离。這時候哥艇,MySQL 會把內(nèi)存的臟頁都flush 到磁盤上,這樣下次 MySQL 啟動的時候草冈,就可以直接從磁盤上讀數(shù)據(jù)她奥,啟動速度會很快。
上面四種場景對性能的影響怎棱?
1.?第三種情況是屬于 MySQL 空閑時的操作哩俭,這時系統(tǒng)沒什么壓力,而第四種場景是數(shù)據(jù)庫本來就要關(guān)閉了拳恋。這兩種情況下凡资,你不會太關(guān)注“性能”問題。
2.?是“redo log 寫滿了谬运,要 flush 臟頁”隙赁,這種情況是 InnoDB 要盡量避免的。因為出現(xiàn)這種情況的時候梆暖,整個系統(tǒng)就不能再接受更新了伞访,所有的更新都必須堵住。如果你從監(jiān)控上看轰驳,這時候更新數(shù)會跌為 0厚掷。
3.?“內(nèi)存不夠用了弟灼,要先將臟頁寫到磁盤”,這種情況其實是常態(tài)冒黑。InnoDB 用緩沖池(buffer pool)管理內(nèi)存田绑,緩沖池中的內(nèi)存頁有三種狀態(tài):
第一種是,還沒有使用的抡爹;
第二種是掩驱,使用了并且是干凈頁;
第三種是冬竟,使用了并且是臟頁欧穴。
而當(dāng)要讀入的數(shù)據(jù)頁沒有在內(nèi)存的時候,就必須到緩沖池中申請一個數(shù)據(jù)頁诱咏。這時候只能把最久不使用的數(shù)據(jù)頁從內(nèi)存中淘汰掉:如果要淘汰的是一個干凈頁苔可,就直接釋放出來復(fù)用缴挖;但如果是臟頁呢袋狞,就必須將臟頁先刷到磁盤,變成干凈頁后才能復(fù)用映屋。
刷臟頁雖然是常態(tài)苟鸯,但是出現(xiàn)以下這兩種情況,都是會明顯影響性能的:
1. 一個查詢要淘汰的臟頁個數(shù)太多棚点,會導(dǎo)致查詢的響應(yīng)時間明顯變長早处;
2. 日志寫滿,更新全部堵住瘫析,寫性能跌為 0砌梆,這種情況對敏感業(yè)務(wù)來說,是不能接受的贬循。
InnoDB 刷臟頁的控制策略
你要正確地告訴 InnoDB 所在主機(jī)的 IO 能力咸包,這樣 InnoDB 才能知道需要全力刷臟頁的時候,可以刷多快杖虾。
就要用到 innodb_io_capacity 這個參數(shù)了烂瘫,它會告訴 InnoDB 你的磁盤能力。這個值建議你設(shè)置成磁盤的 IOPS奇适。磁盤的 IOPS 可以通過 fio 這個工具來測試坟比。
InnoDB 的刷盤速度就是要參考這兩個因素:
1.?臟頁比例
2.? redo log 寫盤速度。
參數(shù) innodb_max_dirty_pages_pct 是臟頁比例上限嚷往,默認(rèn)值是 75%葛账。
要盡量避免這種情況,你就要合理地設(shè)置 innodb_io_capacity 的值皮仁,并且平時要多關(guān)注臟頁比例籍琳,不要讓它經(jīng)常接近 75%茄茁。
臟頁比例是通過
Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total 得到的。
MySQL 中的一個機(jī)制巩割,對于每個鄰居數(shù)據(jù)頁裙顽,如果跟它相鄰的數(shù)據(jù)頁也還是臟頁的話,也會被放到一起刷宣谈。
在 InnoDB 中愈犹,innodb_flush_neighbors 參數(shù)就是用來控制這個行為的,值為 1 的時候會有上述的“連坐”機(jī)制闻丑,值為 0 時表示不找鄰居漩怎,自己刷自己的。
如果使用的是 SSD 這類 IOPS 比較高的設(shè)備的話嗦嗡,就建議你把innodb_flush_neighbors 的值設(shè)置成 0勋锤。因為這時候 IOPS 往往不是瓶頸,而“只刷自己”侥祭,就能更快地執(zhí)行完必要的刷臟頁操作叁执,減少 SQL 語句響應(yīng)時間。