MySQL實戰 | 12 爲什麼我的MySQL會突然變慢?

日常中,也許會遇到這種場景,一條 SQL 語句,正常執行速度很快。但是,有時卻變得很慢,而且很難復現,隨機性比較高,並且持續時間短,到底是什麼情況?

之前的文章中,我們說過,MySQL 的每一次更新並沒有每次都寫入磁盤,InnoDB 引擎會先將記錄寫到 redo log 裏,然後在適當的時候,再把這個記錄更新到磁盤。

當內存數據頁跟磁盤數據頁內容不一致的時候,我們稱這個內存頁爲“髒頁”。內存數據寫入到磁盤後,內存和磁盤上的數據頁的內容就一致了,稱爲“乾淨頁”。

那麼,有理由懷疑,是 redo log 寫入磁盤時導致的。

redo log 何時寫入磁盤?

1、redo log 寫滿了,此時系統會停止所有更新操作,把髒頁刷到磁盤;
2、系統內存不足,需要淘汰髒頁,就要把髒頁寫到磁盤;
3、系統空閒時,會進行髒頁清除;
4、系統異常關閉時;

這幾種場景對系統性能的影響:

場景三是在空閒時操作的,對系統沒什麼影響,場景四是系統關閉時,也不需要考慮。

場景一,此時 redo log 寫滿,系統直接不再接受更新,所有的更新都被阻塞,需要儘量避免這種情況。

場景二,內存不足,由於 InnoDB 的策略是儘量使用內存,當要讀入的數據沒有在內存頁時,需要申請新的數據頁,這時就需要從已佔用的內存中淘汰最久不使用的數據頁。若要淘汰的是一個乾淨頁,則直接淘汰;若要淘汰的是一個髒頁,則需要先刷到磁盤,再淘汰。

所以,以下兩種情況會導致查詢突然變慢:
1、該查詢需要淘汰的髒頁較多;
2、redo log 寫滿,更新全部堵住;

InnoDB 需要有控制髒頁比例的機制,來儘量避免上面的這兩種情況。

InnoDB 刷髒頁的控制策略

innodb_io_capacity

通過設置該參數,告訴 InnoDB 主機的磁盤能力,這樣 InnoDB 才能知道需要全力刷髒頁的時候,可以刷多快。

要儘量避免這種情況,你就要合理地設置 innodb_io_capacity 的值,並且平時要多關注髒頁比例,不要讓它經常接近 75%。

其中,髒頁比例是通過 Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total 得到的,具體的命令參考下面的代碼:

mysql> select VARIABLE_VALUE into @a from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
select VARIABLE_VALUE into @b from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
select @a/@b;

innodb_flush_neighbors

該參數表示,刷髒頁時,是否連同“鄰居”一起刷掉。

值爲 1 的時候會有上述的“連坐”機制,值爲 0 時表示不找鄰居,自己刷自己的。

如果是機械硬盤,可以設置爲 1,從而減少隨機 IO;若是 SSD 等高 IOPS 的設備,可以設置爲 0。


關注本公衆號,後臺回覆「2018」即可獲取傳智播客 2018 最新 Python 和 Java 教程。

公衆號提供CSDN資源免費下載服務!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章