隨著時間的推移,刪除 MySQL 中的舊數據變得越來越慢
我有一個在 Amazon MySQL/RDS 上執行的應用程序,需要維護 2 週的事務歷史記錄,之後可以(通常)清除數據。因為這不是一個硬性規則,所以我不能使用按天或按週進行分區來最有效地刪除舊數據。
有幾個表需要清除,其中許多表具有多個索引和外鍵約束(父/子)。
我正在刪除塊中的數據(一次 1000-3000 行)並在每個塊之後送出。刪除一定數量的塊後,清除程式碼會暫停一段時間。
我的問題是這個過程在 10 到 15 分鐘內非常有效,之後我開始看到刪除數據塊的延遲很大。我相信我的 SQL 盡可能高效。我可以在 MySQL 中的哪個位置更好地了解瓶頸?如果我停止我的程式碼並等待 15-20 分鐘,刪除性能會再恢復 10 分鐘。
我會查看 InnoDB 重做日誌文件的大小。
如果您用更改填充重做日誌,則您描述的症狀很典型,這會強制“同步刷新” - MySQL 會阻止進一步的更改,直到它可以通過從緩衝池中刷新臟頁來釋放部分重做日誌。
RDS 過去預設使用非常小的重做日誌文件大小,如果我記得的話,是 128M。多年來,他們不允許改變尺寸。但在過去的幾年裡,他們確實允許改變它。
以下是檢查重做日誌文件大小(以 MB 為單位)的方法:
mysql> SELECT @@innodb_log_file_size / 1024 / 1024;
要更改它,我認為您將使用 RDS 參數組 UI,然後重新啟動您的 RDS 實例以應用更改。
為了監控這一點,我會觀察寫入重做日誌的字節數:
mysql> SHOW GLOBAL STATUS LIKE 'Innodb_os_log_written';
每 10 分鐘左右測量一次,然後繪製它。重做日誌文件的大小是固定的,寫入最終會到達末尾並迴繞到文件的開頭。它們不能覆蓋代表緩衝池中臟頁的日誌中的更改,因此在它們接近這樣做之前,MySQL 會強制同步刷新。
因此,您可以通過以均勻的間隔定期讀取該變數來觀察 Innodb_os_log_written 的速率。將此日誌寫入速率與日誌文件大小進行比較(請記住,預設情況下您有兩個重做日誌文件,因此您的重做日誌容量為 Innodb_log_file_size * 2)。
這允許您估計“我們每 N 分鐘覆蓋整個重做日誌文件”。當刪除速度很快時,這應該(大致)與您的 10-15 分鐘時間段相關。
我想我記得這個計算有一些細微差別…… Innodb_os_log_written 可能包括一些覆蓋,即在某些情況下,一些寫入會向後尋找以重新寫入塊。因此,在某些情況下,數字可能不會相加。我不知道這裡的詳細資訊。
無論如何,如果您增加重做日誌的大小,InnoDB 早就知道能夠更好地處理繁重的寫入工作量。在允許的範圍內增加它是很誘人的,但這對於您的大多數日常工作負載來說可能是多餘的,並且寫入流量較小。
也可以看看: