前言
本文介紹為什么洗掉了一部分表資料后,表檔案大小不變,以及有哪些表空間回收的方式,
為什么洗掉表資料后,表檔案大小不變
MySQL 采用的是標記洗掉,需要等待后臺 purge 執行緒洗掉資料,但是,purge 執行緒洗掉資料后,表空間依然不會回收,
對于一個資料頁,洗掉了其中若干行資料,因為還有其他資料,資料頁不會回收,并且,空出來的位置會復用,即使一個資料頁資料都被清空,這個資料頁也不會被回收,而是也用于復用,當需要新創建資料頁時,會直接使用這個可復用的資料頁,
那應該怎么回收表空間呢?答案是重建表,
表空間回收方式
重建表推薦使用 ALTER TABLE t ENGINE = InnoDB; ,在不同的 MySQL 版本中,這條陳述句的執行方式不同,
Copy Table
MySQL5.5 之前采用 Copy Table 方式重建表,Alter 期間,只支持 DML 查詢操作,不支持 DML 更新操作,陳述句為 alter table t engine=innodb, ALGORITHM=copy;,
1、server 層創建與原表結構相同的臨時表
2、根據主鍵遞增順序,將一行一行的資料讀出并寫入到臨時表,直至全部寫入完成
3、互換原表和臨時表表名
4、洗掉臨時表
Online DDL
MySQL5.6 開始采用 Inplace 方式重建表,Alter 期間,支持 DML 查詢和更新操作,陳述句為 alter table t engine=innodb, ALGORITHM=inplace;,之所以支持 DML 更新操作,是因為資料拷貝期間會將 DML 更新操作記錄到 Row log 中,
重建程序中最耗時的就是拷貝資料的程序,這個程序中支持 DML 查詢和更新操作,對于整個 DDL 來說,鎖時間很短,就可以近似認為是 Online DDL,
1、獲取 MDL(Meta Data Lock)寫鎖,innodb 內部創建與原表結構相同的臨時檔案
2、拷貝資料之前,MDL 寫鎖退化成 MDL 讀鎖,支持 DML 更新操作
3、根據主鍵遞增順序,將一行一行的資料讀出并寫入到臨時檔案,直至全部寫入完成,并且,會將拷貝期間的 DML 更新操作記錄到 Row log 中
4、上鎖,再將 Row log 中的資料應用到臨時檔案
5、互換原表和臨時表表名
6、洗掉臨時表
注意,兩種拷貝方式都需要額外的一份存盤空間,所以,在存盤空間不足的情況下,重建表會失敗,
對于大表的重建,十分消耗 IO 和 CPU 資源,如果是線上服務,為了安全性考慮,建議使用 GitHub 開源的 gh-ost 來做,
Online和Inplace
Inplace 替換,表示在 InnoDB 內部完成了重建程序,不是在 server 層,
Online 采用的就是 Inplace 的重建方式,但是,Inplace 方式并不一定是 Online,比如添加全文索引時 alter table t add FULLTEXT(field_name); 就不是 Online 的,因為它會阻塞 DML 更新操作;而 Online DDL 一定是 Inlpace 方式的,
alter table、analyze table和optimize table解釋
alter table t engine = innode;(也就是 recreate)就是 Online DDL 重建表程序;
analyze table t; 不是重建表程序,它只是對索引資訊重新統計,會上 MDL 讀鎖;
optimize table t;是 recreate + analyze 程序,
參考
- [1] 為什么表資料刪掉一半,表檔案大小不變
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/300344.html
標籤:其他
上一篇:MySQL45講之表空間回收
下一篇:2105 課程筆記
