任務背景
接到金山雲報警短信,說某數據庫的容量已經達到了90%的水位線,於是登陸控制檯查看詳細情況。
在控制檯首先發現,每一天的磁盤容量的確有所波動,那麼就證明開發人員寫的“資源回收”模塊是在正常運行的,如圖:
那麼就說明沒有什麼數據是可以刪的,既然刪不掉多餘的數據又不想多掏錢擴磁盤容量,只能從“磁盤碎片”下手了。而InnoDB
引擎清理磁盤碎片的命令就是OPTIMIZE
。
具體操作
首先我先查詢一下所有的“磁盤碎片情況”,使用語句如下:
select CONCAT(TABLE_SCHEMA,'.',TABLE_NAME) as 數據表名,concat(truncate(sum(DATA_LENGTH+DATA_FREE+INDEX_LENGTH)/1024/1024,2),' MB') as total_size, concat(truncate(sum(DATA_LENGTH)/1024/1024,2),' MB') as data_size,concat(truncate(sum(DATA_FREE)/1024/1024,2),' MB') as data_free, concat(truncate(sum(INDEX_LENGTH)/1024/1024,2),'MB') as index_size from information_schema.tables group by TABLE_NAME order by data_length desc;
或者使用select table_schema, table_name, data_free, engine from information_schema.tables where table_schema not in ('information_schema', 'mysql') and data_free > 0;
也可以,這個是查詢data_free
大於0的所有表。
然後看到我這個叫history_device_flow_day
的表裏情況如下:
表裏的data_free
就是磁盤碎片的量,比如我現在要幹掉history_device_flow_day
裏所有的磁盤碎片,是975MB,於是先查詢一下這個history_device_flow_day
的存儲引擎,使用語句如下:
show table status from jsonlinef***ds where name='history_device_flow_day';
上面語句裏的jsonlinef***ds
是對應的數據庫,看到的效果如下:
存儲引擎是InnoDB
,那麼就可以啓動清除碎片的語句了:OPTIMIZE TABLE 數據表表名;
,因爲OPTIMIZE TABLE
只對MyISAM
、BDB
和InnoDB
表起作用。
再執行了OPTIMIZE TABLE history_device_flow_day;
之後,大約9分鐘,就會看到“OK”的字樣:
估計有的朋友會問,那上面不是明明寫了“Table does not support optimize, doing recreate + analyze instead”嗎?這個其實無妨,實際上磁盤碎片已經被清除掉了。我們可以再用一次查詢磁盤碎片的命令看一下,如圖:
的確釋放了900多M。
或者使用ALTER TABLE 表名 ENGINE = Innodb;
(只是InnoDB
的表可以這麼做)來達到清理磁盤碎片的目的,這個命令表面上看什麼也不做,實際上是重新整理碎片了。當執行優化操作時,實際執行的是一個空的ALTER
命令,但是這個命令也會起到優化的作用,它會重建整個表,刪掉未使用的空白空間。
補充
爲什麼會產生磁盤碎片?那是因爲某一個表如果經常插入數據和刪除數據,必然會產生很多未使用的空白空間,這些空白空間就是不連續的碎片,這樣久而久之,這個表就會佔用很大空間,但實際上表裏面的記錄數卻很少,這樣不但會浪費空間,並且查詢速度也更慢。
注意!OPTIMIZE
操作會暫時鎖住表,而且數據量越大,耗費的時間也越長,它畢竟不是簡單查詢操作。所以把OPTIMIZE
命令放在程序中是不妥當的,不管設置的命中率多低,當訪問量增大的時候,整體命中率也會上升,這樣肯定會對程序的運行效率造成很大影響。比較好的方式就是做個shell,定期檢查mysql中 information_schema
.TABLES
字段,查看DATA_FREE
字段,大於0的話,就表示有碎片,然後啓動腳本。
參考資料
http://pengbotao.cn/mysql-suipian-youhua.html
http://irfen.me/mysql-data-fragmentation-appear-and-optimization/
最後的最後,如果您覺得本文對您升職加薪有幫助,那麼請不吝贊助之手,刷一下下面的二維碼,贊助本人繼續寫更多的博文!