optimize 回收表空間的一些說明
- 2019 年 10 月 4 日
- 筆記
optimize命令回收表空間的說明
線上伺服器,有張大表需要用pt-archiver根據時間劃分歸檔大量數據到另一個新表中。原先200G的表,在歸檔完成後,du -hs 顯示依然是200G的大小,刪除了大量的行記錄但是實際上空間是不會釋放的。
這種情況下,我們就要使用optimize命令重建表以達到釋放表空間的目的。
(好像是從5.6.6之後,optimize不鎖表了,但是optimize操作會進行rebuild表操作,要確保磁碟剩餘空間足夠存放新表的大小,不然操作會失敗)
另外,如果在主庫執行optimize table會造成從庫延遲,這種情況下,可以使用 optiminze no_write_to_binlog table xxxx ; 這樣就不會把optimize操作寫入binlog。主庫執行完後,再到從庫執行optimize table操作。
姜承堯的py_innodb_page_info 工具 下載地址:http://pan.baidu.com/s/1c2o0Tag
模擬過程如下:
use test; CREATE TABLE `t` ( `a` int(10) unsigned NOT NULL AUTO_INCREMENT, `b` char(10) DEFAULT NULL, PRIMARY KEY (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; insert into t (b) select 'aaaaaaa'; insert into t(b) select b from t;
多執行幾次這個命令,造出大量的行數據
然後使用py_innodb_page_info分析page,如下,可以看到存了數據的page很多【下圖紅色部分】
[root@master /root/py_innodb_page_type ]#./py_innodb_page_info.py -v /data/mysql/test/t.ibd page offset 00000000, page type <FileSpace Header> page offset 00000001, page type <Insert BufferBitmap> page offset 00000002, page type <FileSegment inode> page offset 00000003, page type<B-tree Node>, page level <0000> page offset 00000004, page type<B-tree Node>, page level <0000> page offset 00000005, page type<B-tree Node>, page level <0000> page offset 00000006, page type<B-tree Node>, page level <0000> page offset 00000007, page type<B-tree Node>, page level <0000> page offset 00000008, page type<B-tree Node>, page level <0000> page offset 00000009, page type<B-tree Node>, page level <0000> page offset 0000000a, page type<B-tree Node>, page level <0000> page offset 0000000b, page type<B-tree Node>, page level <0000> page offset 0000000c, page type<B-tree Node>, page level <0000> page offset 0000000d, page type<B-tree Node>, page level <0000> page offset 0000000e, page type<B-tree Node>, page level <0000> page offset 0000000f, page type<B-tree Node>, page level <0000> page offset 00000010, page type<B-tree Node>, page level <0000> page offset 00000000, page type <Freshly AllocatedPage> page offset 00000000, page type <FreshlyAllocated Page> Total number of page: 19: Freshly Allocated Page: 2 Insert Buffer Bitmap: 1 File Space Header: 1 B-tree Node: 14 File Segment inode: 1
然後大量刪除數據
delete from test.t where a>100;
開始刪除大量的數據(只保留100條記錄,確保數據應該在第一個數據頁存的下)
然後用hexdump去看下innodb的第二個page資訊
hexdump -C -s 65536 -n 16384 /data/mysql/test/t.ibd
發現這個page的數據還是很多,它們並沒有被真正的刪除 (實際上當一條記錄被刪除後,該空間只是標記為空閑了,它會被加入到空間鏈表裡面)
### hexdump命令說明:
## -s 從啥位置開始取數據,-n 取出多少bytes的數據。
## 因為每個page 16k。InnoDB前3個page是存放其它數據的。第一個data page是從16*1024*3=49152位置開始的。第二個data page是從16*1024*4=65536開始的。
重建下test.t表試試效果:
root@localhost [test]> optimize table t;
再次使用py_innodb_page_info分析page,如下,可以看到page少了很多【下圖紅色部分】,基本上都被回收了。
[root@master /root/py_innodb_page_type ]#./py_innodb_page_info.py -v /data/mysql/test/t.ibd page offset 00000000, page type <FileSpace Header> page offset 00000001, page type <InsertBuffer Bitmap> page offset 00000002, page type <FileSegment inode> page offset 00000003, page type<B-tree Node>, page level <0000> page offset 00000000, page type <FreshlyAllocated Page> page offset 00000000, page type <FreshlyAllocated Page> Total number of page: 6: Freshly Allocated Page: 2 Insert Buffer Bitmap: 1 File Space Header: 1 B-tree Node: 1 File Segment inode: 1
然後再用hexdump去看下innodb的第二個page資訊,發現這個page的數據已經全部是0了,是一個空白的page
[root@master /tmp ]# hexdump -C -s 65536 -n16384 /data/mysql/test/t.ibd 00010000 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 |................| * 00014000