MySQL -- 空間回收
空洞: 可以被複用但沒有被使用的空間 ,經過大量 增刪改 的表,都會存在空洞
刪除
- 如果刪掉
R4
,InnoDB只會將R4
標記為刪除 ,如果再插入 300~600 的記錄時,可能會 複用 這個位置,但磁碟檔案不會縮小- 記錄的複用 ,僅限於 符合範圍 條件的資料
- 如果刪除了 一個數據頁上的所有記錄 ,那麼 整個資料頁 都可以被 複用 的
- 當 整個頁 從B+樹裡摘除後,可以被複用到 任何位置
- 如果將
page A
上的所有記錄刪除後,page A
會被 標記為可複用- 當插入ID=50的記錄時,需要 申請新頁 時
page A
可以被複用
- 當插入ID=50的記錄時,需要 申請新頁 時
- 如果 相鄰 的兩個資料頁 利用率 都很小
- 系統會把這兩個資料頁上的資料 合併 到其中一個頁上,另一個數據頁就會被標記為 可複用
- 如果通過
DELETE
命令 刪除整個表 ,那麼 所有的資料頁 都會被 標記為可複用 ,但磁碟上的檔案同樣不會變小 -
TRUNCATE
=DROP
+CREATE
插入
- 如果資料是 隨機插入 的,就有可能造成 索引的資料頁分裂
-
page A
已滿,如果再插入ID=550的資料,就必須申請一個新的頁面page B
來儲存資料,導致 頁分裂 ,留下了空洞
更新
更新 索引 上的值,等同於 先邏輯刪除舊值後再插入新值 ,同樣也會造成 空洞
重建表
邏輯過程
- 新建一個與表A 結構相同 的表B
- 按照 主鍵遞增 的順序,把表A中的資料一行一行讀出,然後再插入表B
- 表B的主鍵索引更 緊湊 ,資料頁的 利用率 也更高
- 表B作為 臨時表 ,資料從表A匯入到表B,然後用表B替換A
重建命令
ALTER TABLE A ENGINE=InnoDB;
ALTER TABLE
預設會 提交前面的事務
Before MySQL 5.5
- 與上述的邏輯過程類似,MySQL 自動完成 轉存資料,交換表名和刪除舊錶等操作
- 時間消耗最多的是往 臨時表 ( Server層 )插入資料的過程,在這個過程中,如果 新資料 要寫入表A,就會造成 資料丟失
- 因此整個DDL過程中,表A是不能執行DML的,即不是 Online 的
- MySQL 5.6引入 Online DDL
Since MySQL 5.6
- 建立一個 臨時檔案 ( InnoDB內部 ),掃描表A主鍵的所有資料頁
- 用資料頁中表A的記錄生成B+樹,儲存到臨時檔案
- state 2( 日誌 ):生成臨時檔案的過程中,將所有對A的 操作 記錄在一個 日誌檔案 ( row log )中
- state 3( 重放 ):臨時檔案生成後,將日誌檔案的操作 應用到臨時檔案 ,得到一個 邏輯資料 上與表A相同的資料檔案
- 用最新的臨時檔案替換表A的資料檔案
MDL鎖
-
ALTER
語句在 啟動 時需要獲取 MDL寫鎖 ,但會在 真正拷貝資料之前退化為MDL讀鎖- MDL讀鎖 不會阻塞 其他執行緒對這個表的 DML ,同時又能 阻塞 其他執行緒對這個表的 DDL
- 對一個大表來說,
Online DDL
最耗時的過程是 拷貝資料到臨時表 的過程,期間是可以接受DML- 相對於整個DDL過程來說, 鎖的時間非常短 ,對 業務 來說,可以認為是
Online
- 相對於整個DDL過程來說, 鎖的時間非常短 ,對 業務 來說,可以認為是
效能消耗
- 重建表會 掃描原表資料 和 構建臨時檔案(或臨時表)
- 對於大表來說,重建表會 非常消耗IO和CPU資源
- 推薦工具:
gh-ost
Online + Inplace
-
tmp_table
是一個 臨時表 ,在 Server 層建立的 -
tmp_file
是 臨時檔案 ,在 InnoDB 內部建立的, 整個DDL過程都在InnoDB內部完成- 對於 Server 層來說,並沒有把資料挪動到 臨時表 ,是個原地操作( Inplace )
- DDL過程如果是Online的,那一定是Inplace的,反之不成立
-
ALTER TABLE t ADD FULLTEXT(field_name);
是 Inplace 的,但會阻塞DML( 非Online )
-
ALTER TABLE A ENGINE=InnoDB; 等同於 mysql> ALTER TABLE t ENGINE=InnoDB, ALGORITHM=INPLACE; Query OK, 0 rows affected (0.68 sec) Records: 0Duplicates: 0Warnings: 0
與 Inplace 對應的是 Copy ,強制拷貝表到 Server 層
mysql> ALTER TABLE t ENGINE=InnoDB, ALGORITHM=COPY; Query OK, 100000 rows affected (1.46 sec) Records: 100000Duplicates: 0Warnings: 0
ALTER + ANALYZE + OPTIMIZE
-
ALTER TABLE t ENGINE=InnoDB
: 重建表 -
ANALYZE TABLE t
:觸發 表索引資訊的重新取樣統計 -
OPTIMIZE TABLE t
:ALTER
+ANALYZE
參考資料
《MySQL實戰45講》
轉載請註明出處:http://zhongmingmao.me/2019/02/01/mysql-reclaim-space/
訪問原文「MySQL -- 空間回收」獲取最佳閱讀體驗並參與討論