一次性刪除海量數據會導致長時間鎖表、阻塞業務查詢、甚至引發主從復制延遲。本文介紹「分而治之」策略,將大刪除拆解為小批次,並配合間歇性暫停,平滑釋放資源。
定期清理三個月前的舊數據:
DELETE FROM messages WHERE dt < DATE_SUB(NOW(), INTERVAL 3 MONTH);
若涉及百萬行以上,單條 SQL 會:
Seconds_Behind_Master 飆升rows_affected = 0
do {
rows_affected = do_query("
DELETE FROM messages
WHERE dt < DATE_SUB(NOW(), INTERVAL 3 MONTH)
LIMIT 10000
")
} while rows_affected > 0
每次刪 1 萬行,配合 LIMIT 控制事務大小。若再加入 SLEEP(0.5),可將壓力分散到更長時間窗口。
| 參數 | 建議值 | 說明 |
|---|---|---|
| 單批次行數 | 5,000 ~ 50,000 | 視行大小、索引數量調整 |
| 批次間隔 | 0.1 ~ 1 秒 | 用 SELECT SLEEP(0.5) 或應用層控制 |
| 事務隔離級別 | READ COMMITTED | 減少間隙鎖,配合 binlog_format=ROW |
若表有自增主鍵,可先查出需刪除的 ID 範圍,再按區間循環刪除,避免全表掃描:
-- 獲取邊界 SELECT MIN(id), MAX(id) FROM messages WHERE dt < '2024-01-01'; -- 分段刪除 DELETE FROM messages WHERE id BETWEEN 100000 AND 109999 AND dt < '2024-01-01';
大數據刪除三原則:小事務、分批次、加間隔。配合 pt-archiver 等工具可實現自動化、可監控的歸檔刪除。