不要在 Production MySQL Server 上刪除資料表(< 8.0.23)
背景
前陣子團隊裡在討論,有用不到的 Table 要刪掉,是否要用一個月一次深夜停機的時段。我們團隊裡資深的同事表示他記得會有整個 DB 的 Lock 。我就想,照官方文件,Online DDL 應該不影響其他操作啊,而且也是針對該資料表。那平常的時間就可以刪啦?
不過又多做了一些搜尋,發現果然薑還是老的辣。。。
看到了這篇文章: Why you simply don't drop a huge InnoDB table in production...
DROP table 會怎樣?
那篇文章,以及後來我找到官方的相關 Bug 和 Blog 提到,在 MySQL 8.0.23 之前,有個問題導致 DROP table 時會短暫 block 整個 DB 的讀寫。。。
為什麼呢? MySQL 記憶體區裡有一個資料結構叫 Buffer Pool。簡單來說就是一個鏈狀列表,每一個節點就是一個快取單位,會儲存最近存取過的資料,且是一種 LRU 快取。 大部分 MySQL 占用的記憶體都是放這個資料結構。當刪除一張資料表時,MySQL 竟然會遍歷這張表,把快取中屬於那張表的資料都刪掉。當這個快取非常大(比如說線上的伺服器記憶體開很大),那這個清理就會跑很久,那就會 Block 住整個 DB ,因為所有的動作都會讀取這個列表。
8.0.23之後的修正也很簡單,也就是不刪那些資料了。那些節點會被重複利用。
TRUNCATE 也最好不要
如果沒辦法升級? 怎麼辦
如果有需要刪除表,但用的是舊版的 MySQL,可以用同篇文章介紹的DELETE + OPTIMIZE + DROP
。我就沒有仔細研究因為我們後來決定不刪了XD。