1. 程式人生 > 其它 >MySQL45講之表空間回收

MySQL45講之表空間回收

本文介紹為什麼刪除了一部分表資料後,表文件大小不變,以及有哪些表空間回收的方式。

前言

本文介紹為什麼刪除了一部分表資料後,表文件大小不變,以及有哪些表空間回收的方式。

為什麼刪除表資料後,表文件大小不變

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 過程。

參考