1唤锉、 更新操作為什么突然變慢
平時(shí)的工作中,可能會(huì)遇到過(guò)這樣的場(chǎng)景别瞭,一條 SQL 語(yǔ)句窿祥,正常執(zhí)行的時(shí)候特別快,但是有時(shí)也不知道怎么回事蝙寨,它就會(huì)變得特別慢晒衩,并且這樣的場(chǎng)景很難復(fù)現(xiàn),它不只隨機(jī)墙歪,而且持續(xù)時(shí)間還很短听系。
看上去就像數(shù)據(jù)庫(kù)“抖動(dòng)”了一下,這種情況的可能原因是在刷臟頁(yè)(flush)
虹菲,也就是寫(xiě)內(nèi)存和日志靠胜,將內(nèi)存和日志里的更改記錄到磁盤(pán)里,然后空出內(nèi)存或者日志資源。
當(dāng)內(nèi)存數(shù)據(jù)頁(yè)跟磁盤(pán)數(shù)據(jù)頁(yè)內(nèi)容不一致的時(shí)候浪漠,我們稱(chēng)這個(gè)內(nèi)存頁(yè)為“臟頁(yè)”
陕习。內(nèi)存數(shù)據(jù)寫(xiě)入到磁盤(pán)后,內(nèi)存和磁盤(pán)上的數(shù)據(jù)頁(yè)的內(nèi)容就一致了郑藏,稱(chēng)為“干凈頁(yè)”
衡查。
根據(jù)mysql實(shí)戰(zhàn)(二) 一條SQL更新語(yǔ)句的執(zhí)行過(guò)程里提到的WAL(先寫(xiě)日志,之后再寫(xiě)磁盤(pán))
技術(shù)必盖,數(shù)據(jù)庫(kù)將隨機(jī)寫(xiě)轉(zhuǎn)換成了順序?qū)懓枭蟠筇嵘藬?shù)據(jù)庫(kù)性能。但是同時(shí)也帶來(lái)上述說(shuō)的臟頁(yè)歌粥、干凈頁(yè)
的問(wèn)題塌忽。
2、觸發(fā)刷臟頁(yè)的時(shí)機(jī)
臟頁(yè)會(huì)被后臺(tái)線(xiàn)程自動(dòng) flush 失驶,也會(huì)由于數(shù)據(jù)頁(yè)淘汰而觸發(fā) flush 土居,而刷臟頁(yè)的過(guò)程由于會(huì)占用資源,可能會(huì)讓你的更新和查詢(xún)語(yǔ)句的響應(yīng)時(shí)間長(zhǎng)一些嬉探。那么什么時(shí)候會(huì)引發(fā)數(shù)據(jù)庫(kù)的 flush 過(guò)程呢?
第一種場(chǎng)景是擦耀,新增數(shù)據(jù)時(shí),先寫(xiě)日志的日志文件(InnoDB的redo log)寫(xiě)滿(mǎn)了涩堤,需要擦除一些眷蜓,才能繼續(xù)插入數(shù)據(jù)。這是系統(tǒng)會(huì)停下所有更新操作胎围,進(jìn)行redo log文件的數(shù)據(jù)擦除工作吁系。
第二種場(chǎng)景是,系統(tǒng)內(nèi)存不足白魂。當(dāng)需要新的內(nèi)存頁(yè)加載數(shù)據(jù)時(shí)汽纤,需要淘汰一些舊的數(shù)據(jù)頁(yè),如果這個(gè)數(shù)據(jù)頁(yè)是
臟頁(yè)
福荸,就需要先將臟頁(yè)
寫(xiě)入磁盤(pán)蕴坪。第三種場(chǎng)景,系統(tǒng)比較空閑的時(shí)候逞姿,只要一有機(jī)會(huì)辞嗡,就會(huì)刷一點(diǎn)臟頁(yè)。
第四種場(chǎng)景滞造,mysql正常關(guān)閉時(shí)续室,會(huì)把內(nèi)存中的臟頁(yè)都 flush 到磁盤(pán)上,這樣下次mysql啟動(dòng)時(shí)就可以直接從磁盤(pán)上讀數(shù)據(jù)谒养,啟動(dòng)速度會(huì)很快挺狰。
3明郭、頻繁刷臟頁(yè)的處理辦法
第三、四種場(chǎng)景下丰泊,對(duì)系統(tǒng)壓力很小薯定,不會(huì)有太多“性能”問(wèn)題。
第一種是“redo log 寫(xiě)滿(mǎn)了瞳购,要 flush 臟頁(yè)”话侄,這種情況是 InnoDB 要盡量避免的。因?yàn)槌霈F(xiàn)這種情況的時(shí)候学赛,整個(gè)系統(tǒng)就不能再接受更新了年堆,所有的更新都必須堵住。第二種是“內(nèi)存不夠用了盏浇,要先將臟頁(yè)寫(xiě)到磁盤(pán)”变丧,這種情況其實(shí)是常態(tài)。
刷臟頁(yè)雖然是常態(tài)绢掰,但是出現(xiàn)以下這兩種情況痒蓬,都是會(huì)明顯影響性能的:
- 一個(gè)查詢(xún)要淘汰的臟頁(yè)個(gè)數(shù)太多,會(huì)導(dǎo)致查詢(xún)的響應(yīng)時(shí)間明顯變長(zhǎng)滴劲;
- 日志寫(xiě)滿(mǎn)攻晒,更新全部堵住,寫(xiě)性能跌為 0班挖,這種情況對(duì)敏感業(yè)務(wù)來(lái)說(shuō)炎辨,是不能接受的。
所以聪姿,InnoDB 需要有控制臟頁(yè)比例的機(jī)制,來(lái)盡量避免上面的這兩種情況乙嘀。
InnoDB 臟頁(yè)的控制策略末购,是根據(jù) InnoDB 所在主機(jī)的 IO 能力, InnoDB 決定刷臟頁(yè)的時(shí)候虎谢,要刷多快盟榴。
和這些策略相關(guān)的配置參數(shù):
-
innodb_io_capacity
這個(gè)參數(shù)它會(huì)告訴 InnoDB 你的磁盤(pán)能力。這個(gè)值我建議你設(shè)置成磁盤(pán)的 IOPS婴噩。磁盤(pán)的 IOPS 可以通過(guò) fio 這個(gè)工具來(lái)測(cè)試. -
innodb_max_dirty_pages_pct
是臟頁(yè)比例上限擎场,默認(rèn)值是 75%,平時(shí)要多關(guān)注臟頁(yè)比例几莽,不要讓它經(jīng)常接近 75%迅办。 -
innodb_flush_neighbors
參數(shù)就是用來(lái)控制是否連帶刷掉當(dāng)前臟頁(yè)附近的“鄰居臟頁(yè)”,值為 1 的時(shí)候會(huì)有上述的“連坐”機(jī)制章蚣,值為 0 時(shí)表示不找鄰居站欺,自己刷自己的。mysql8.0開(kāi)始,默認(rèn)值已經(jīng)是0了矾策。