MySQL45講之表空間回收
前言
本文介紹為什麼刪除了一部分表資料後,表文件大小不變,以及有哪些表空間回收的方式。
為什麼刪除表資料後,表文件大小不變
MySQL 採用的是標記刪除,需要等待後臺 purge 執行緒刪除資料。但是,purge 執行緒刪除資料後,表空間依然不會回收。
對於一個數據頁,刪除了其中若干行資料,因為還有其他資料,資料頁不會回收,並且,空出來的位置會複用。即使一個數據頁資料都被清空,這個資料頁也不會被回收,而是也用於複用,當需要新建立資料頁時,會直接使用這個可複用的資料頁。
那應該怎麼回收表空間呢?答案是重建表。
表空間回收方式
重建表推薦使用 ALTER TABLE t ENGINE = InnoDB;
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 查詢和更新操作,對於整個 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 過程。