Intro
MySQL中刪除比較大的表時,如果直接用drop table
的方式進行刪除,有可能會對整個實例產生影響甚至使得實例夯住。因此可以通過硬鏈接的方式對表進行刪除,使得對生產環境的影響降到最低。
drop table 的過程
- 持有 buffer pool mutex;
- 持有 buffer pool 中的 flush list mutex;
- 開始掃描 LRU list:
- 如果 dirty page 屬於 drop table,那么就直接從 LRU list 中移除;
- 如果刪除的 page 個數超過了
define buf_lru_drop_search_size 1024
的話,則釋放 buffer pool mutex 和 flush list mutex ,強制通過 pthread_yield 進行一次 os context switch ,釋放 cpu 時間片; - 重新持有 buffer pool mutex 和 flush list mutex,繼續遍歷 LRU list,直到 LRU 的表頭。
- 釋放 flush list mutex;
- 釋放 buffer pool mutex。
- 再次重復上述的 1-5 步驟,只不過 1-5 是刪除 dirty page,這次的重復執行,刪除的是 buffer pool 中的 clean page。
簡單來看,整個過程可以簡化為:
- 獲取 buffer pool mutex 和 flush list mutex;
- 從尾部開始遍歷 LRU 鏈表;
- 如果是 dirty page,那么將 dirty page 置為 clean page,並從 flush list 中刪除;
- 然后進行第二次遍歷 LRU,將 page 從 LRU 中移動到 free list 中;
- 釋放 buffer pool mutex 和 flush list mutex。
在整個刪除表的過程中,持有了 buffer pool mutex 和 flush list mutex ,如果整個 buffer pool 比較大,或者表有較多的臟頁,那么持有鎖的時間會比較長,導致其他事務在用到這個 buffer pool 的時候被阻塞,現象上來看就是這個實例被夯住。
硬鏈接刪除表
- 主庫和從庫上對表建立硬鏈接
ln table_1.ibd table_1.ibd.hdlk
ln table_1.frm table_1.frm.hdlk
- 在主庫進行 drop table
drop table table_1;
- 在 os 層刪除物理文件
rm table_1.ibd.hdlk
rm table_1.frm.hdlk
- 如果表達到 500G 或者上 TB,則可以用 truncate 命令進行截斷刪除
truncate -s 2G table_1.ibd.hdlk