轉自
Mysql刪除數據后,磁盤空間未釋放的解決辦法 - 今日頭條(TouTiao.com)
http://toutiao.com/a6303087712678412546/?tt_from=mobile_qq&utm_campaign=client_share&app=news_article&utm_source=mobile_qq&iid=4710631352&utm_medium=toutiao_ios
起因:
公司的服務器上添加了硬盤監控,收到報警后,確認是mysql的文件占用空間比較大。於是,確認是哪個表占空間比較大后,刪除了部分數據(注:數據庫數據為線下分析使用,非線上數據,可以刪除),但服務器硬盤空間並沒有釋放掉,報警仍舊存在。
原因及解決辦法:
使用delete刪除的時候,mysql並沒有把數據文件刪除,而是將數據文件的標識位刪除,沒有整理文件,因此不會徹底釋放空間。被刪除的數據將會被保存在一個鏈接清單中,當有新數據寫入的時候,mysql會利用這些已刪除的空間再寫入。即,刪除操作會帶來一些數據碎片,正是這些碎片在占用硬盤空間。(BTW:看官方文檔上好像是innodb引擎的可以利用操作系統來幫忙回收這些碎片,MyISam的表沒有辦法自己回收,這里待定,后續再看下)
官方推薦使用 OPTIMIZE TABLE命令來優化表,該命令會重新利用未使用的空間,並整理數據文件的碎片。
語法如下:
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
注:該命令將會整理表數據和相關的索引數據的物理存儲空間,用來減少占用的磁盤空間,並提高訪問表時候的IO性能。但是,具體對表產生的影響是依賴於表使用的存儲引擎的。該命令對視圖無效。
該命令目前只對MyISAM、InnoDB,ARCHIVE的表起作用,其余引擎的不起作用,不過可以設置,后面會講到~~
具體的使用例子:
1、查看表占用的空間大小:
大約占用了51G的空間。
2、使用optimize命令
使用的時間比較長,需要耐心等待。
3、查看優化之后的空間占用大小。
占用空間15G左右,減少了大部分。
可見優化效果很好~
BTW:
查看表占用硬盤空間大小的SQL語句如下:(默認用M做展示單位)
SELECT TABLE_NAME, (DATA_LENGTH+INDEX_LENGTH)/1048576, TABLE_ROWS FROM information_schema.tables WHERE TABLE_SCHEMA='dbname' AND TABLE_NAME='tablename';
對於InnoDB引擎的mysql, optimize 命令,將會被映射到alter table上,具體可以參見官方文檔。
補充:
1、如何使optimize 支持其他引擎?
默認情況下,optimize不支持其他存儲引擎,但是可以在啟動mysqld的時候,使用 --skip-new 參數,這種情況下,optimize命令,將會被映射到alter table命令上,實現上述的功能。
2、該物理刪除還是邏輯刪除?
生產環境下,盡量不要用物理刪除,一旦物理刪除了,意味着數據恢復就會很麻煩。建議邏輯刪除,數據仍存儲在DB里。如果數據量很大的時候,可以考慮使用分庫分表。但,這個仍舊是需要根據業務場景來。
3、optimize執行時會將表鎖住,所以不要在高峰期使用。也不要經常使用,每月一次就足夠了