不要在 Production MySQL Server 上刪除資料表(< 8.0.23)

·

1 min read

背景

前陣子團隊裡在討論,有用不到的 Table 要刪掉,是否要用一個月一次深夜停機的時段。我們團隊裡資深的同事表示他記得會有整個 DB 的 Lock 。我就想,照官方文件,Online DDL 應該不影響其他操作啊,而且也是針對該資料表。那平常的時間就可以刪啦?

不過又多做了一些搜尋,發現果然薑還是老的辣。。。

看到了這篇文章: Why you simply don't drop a huge InnoDB table in production...

DROP table 會怎樣?

那篇文章,以及後來我找到官方的相關 BugBlog 提到,在 MySQL 8.0.23 之前,有個問題導致 DROP table 時會短暫 block 整個 DB 的讀寫。。。

為什麼呢? MySQL 記憶體區裡有一個資料結構叫 Buffer Pool。簡單來說就是一個鏈狀列表,每一個節點就是一個快取單位,會儲存最近存取過的資料,且是一種 LRU 快取。 大部分 MySQL 占用的記憶體都是放這個資料結構。當刪除一張資料表時,MySQL 竟然會遍歷這張表,把快取中屬於那張表的資料都刪掉。當這個快取非常大(比如說線上的伺服器記憶體開很大),那這個清理就會跑很久,那就會 Block 住整個 DB ,因為所有的動作都會讀取這個列表。

8.0.23之後的修正也很簡單,也就是不刪那些資料了。那些節點會被重複利用。

TRUNCATE 也最好不要

TRUNCATE 其實就是 DROP + CREATE

如果沒辦法升級? 怎麼辦

如果有需要刪除表,但用的是舊版的 MySQL,可以用同篇文章介紹的DELETE + OPTIMIZE + DROP。我就沒有仔細研究因為我們後來決定不刪了XD。