RDS MySQL的I/O性能受硬件層存儲介質、軟件層數據庫內核架構和具體SQL語句(掃描或修改數據量)的影響。本文介紹實例I/O高的原因和解決方案。
高吞吐導致實例I/O高
現象
如果表上有很多索引或大字段,頻繁地更新、刪除、插入,讀取數據和刷新臟頁時會有大量的I/O。
您可以在控制臺的
頁面,單擊性能趨勢頁簽,查看讀寫負載情況。解決方案
建議降低讀寫頻率或升級實例規格、優化刷新臟頁相關的參數來解決高吞吐問題。和刷新臟頁相關的參數如下:
innodb_max_dirty_pages_pct:緩沖池中允許的臟頁百分比,默認值為75。
innodb_max_dirty_pages_pct_lwm:臟頁比例的低水位線。當緩沖池里的臟頁比例超過這個低水位線時,能夠觸發臟頁預刷功能,逐步控制臟頁比例。默認值為0,表示禁用該功能。
說明innodb_max_dirty_pages_pct_lwm的值不能大于innodb_max_dirty_pages_pct的值,否則會強制修改為與innodb_max_dirty_pages_pct相同。
innodb_io_capacity:設置InnoDB后臺任務每秒執行的I/O操作數的上限,影響刷新臟頁和寫入緩沖池的速率。默認值為20000。
innodb_io_capacity_max:如果刷新操作過于落后,InnoDB可以超過innodb_io_capacity的限制進行刷新,但是不能超過本參數的值。默認值為40000。
臨時表導致實例I/O高
現象
如果臨時目錄很大,可能存在慢SQL排序、去重等操作導致創建很大的臨時表。臨時表寫入也會造成I/O增加。
您可以在控制臺的
頁面,單擊性能趨勢頁簽,查看tmp或other目錄大小。解決方案
建議進行SQL優化,避免慢SQL。數據庫自治服務DAS提供自助SQL優化功能,具體操作,請參見SQL優化。
讀取冷數據導致實例I/O高
現象
如果SQL查詢或修改的數據不在緩沖池(Buffer Pool),則需要從存儲中讀取,可能會產生大量的I/O吞吐。
您可以在控制臺的
頁面,單擊性能趨勢頁簽,查看Buffer Pool命中率。解決方案
根據業務場景重新設計緩存策略,或者升級實例規格。
DDL語句導致實例I/O高
現象
DDL語句可能會重建表空間,期間會掃描全表數據、創建索引排序、刷新新表產生的臟頁,這些都會導致大量的I/O吞吐。另外一種場景是刪除大表造成的I/O抖動。
您可以在控制臺的監控與報警頁面,單擊標準監控頁簽內的標準視圖,可以查看實例的磁盤空間和IOPS信息。
解決方案
可以使用阿里云自研內核AliSQL提供的異步刪除大文件功能解決問題,更多信息,請參見Purge Large File Asynchronously。
大事務寫Binlog導致實例I/O高
現象
事務只有在提交時才會寫Binlog文件,如果存在大事務,例如一條Delete語句刪除大量的行,可能會產生幾十GB的Binlog文件,Binlog文件刷新到磁盤時,會造成很高的I/O吞吐。
解決方案
建議盡量將事務拆分,避免大事務和降低刷新磁盤頻率。
附:InnoDB I/O系統介紹
InnoDB通過一套獨立的I/O系統來處理數據頁的讀取和寫入,如果SQL請求的數據頁不在Buffer Pool中,會產生物理I/O,需要讀寫底層存儲的數據:
讀數據頁操作
通過同步I/O實現,同步I/O調用底層的讀接口。
寫數據頁操作
通過異步I/O實現,例如后臺線程刷新臟頁,后臺I/O線程會異步的將臟頁刷到磁盤。
除了對普通數據文件的讀寫I/O操作,寫Redo日志、寫Undo日志、寫Binlog日志、排序臨時表、重建DDL表空間等也會造成大量I/O。