案例 - optimize table 的一些坑

線上IM消息的數據庫,磁盤空間使用率已到達96%html


  1. 沒申請到擴容的新機器,沒法作數據庫遷移mysql

  2. 保留的是全量聊天記錄,一條都不準刪sql


在這種場景下,爲了減小空間容量,只能對錶作碎片整理來釋放空間, optimize table數據庫


當咱們使用mysql進行delete數據,delete完之後,發現空間文件ibd並無減小,這是由於碎片空間的存在,舉個例子,一共公司有10號員工,10個座位,被開除了7個員工,但這些座位仍是保留的,碎片整理就像,讓剩下的3個員工都靠邊坐,而後把剩下的7個做爲給砸掉,這樣就能釋放出空間了bash


OPTIMIZE TABLE reorganizes the physical storage of table data and associated index data, to reduce storage space and improve I/O efficiency when accessing the table. app

好處除了減小表數據與表索引的物理空間,還能下降訪問表時的IO,這個比較理解,整理以前,取數據須要跨越不少碎片空間,這時須要時間的,整理後,想要的數據都放在一塊兒了,直接拿就拿到了,效率提升ide


拿一張大表作碎片整理,整理以前是96Gui

[root@localhost myshard]# du -ch tbl_immsg_bigo_96.ibd |grep total
3.5G    total


當執行命令時
spa

optimise table tbl_immsg_bigo_96;


整理完後,剩下2.9Gcode

myshard> optimize no_write_to_binlog table tbl_immsg_bigo_96;
+---------------------------+----------+----------+-------------------------------------------------------------------+
| Table                     | Op       | Msg_type | Msg_text                                                          |
+---------------------------+----------+----------+-------------------------------------------------------------------+
| myshard.tbl_immsg_bigo_96 | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| myshard.tbl_immsg_bigo_96 | optimize | status   | OK                                                                |
+---------------------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (3 min 21.66 sec) 

[root@localhost myshard]# du -ch tbl_immsg_bigo_96.ibd |grep total
2.9G    total



整理期間會有不少慢查詢的告警,在告一個waiting for table metadata lock的狀態


ID: 121                                                  

USER: db_myshard_rw                                            

HOST: 127.0.0.1:56326                                         

DB: myshard                                               

COMMAND: Execute                                                

TIME: 1214                                                  

STATE: Waiting for table metadata lock                                

INFO: insert into myshard.tbl_immsg_bigo_0 (touid,fromuid,fromseqid,appid


wKiom1mU8hGTsMHQAALlk5w5nh0649.jpg-wh_50


這是由於optimize table的本質,是alter table


mysql 5.5 的改表過程以下

1.建立一張新的臨時表 tmp 

2.把舊錶鎖住,禁止插入刪除,只容許讀寫 (這就是爲何上面的insert語句都停留在waiting for table metadata lock)

3.把數據不斷的從舊錶,拷貝到新的臨時表,(這就是上面報copy to tmp table)

4.等表拷貝完後,進行瞬間的rename操做

5.舊錶刪除掉


因此optimize最大的問題是鎖表,鎖表會致使insert,delete,update語句堵住,上面等待了1214秒,還在繼續,因此第一個結論:在使用optimize table的時候,確保不要有任何dml語句,確保業務切走,不然可能會出事故


爲何要鎖表呢?

alter過程裏,數據不停從舊錶拷貝到新表,若是這個時候舊錶被delete了數據了,那舊錶與新表的數據就不一致了,到最後rename 新表 to 舊錶表名 時候,數據量就多了


若是在拷貝數據的過程當中,對舊錶數據的delete,同時對新表也作delete,那數據就一致了,對於update和insert也同樣,這個功能能夠經過 insert觸發器,delete觸發器,update觸發器實現


pt-online-schema-change就利用3個觸發器完成在線改表,也能完成在線碎片整理,命令使用 

--alter="ENGINE=InnoDB"


至關於optimize table的效果


具體命令以下,最好放在腳本里面實現,由於一次不止整理一個表,能夠把整個數據庫的表都碎片整理

 pt-online-schema-change  
  -h地址
  -P端口號
  -u用戶名
  -p密碼   
  --database=數據庫
  t=表名字
  --charset=utf8 
  --max-lag=300 
  --check-interval=5 
  --alter="ENGINE=InnoDB" 
  --max-load="Threads_running:400" 
  --critical-load="Threads_running:400" 
  --nocheck-replication-filters 
  --alter-foreign-keys-method=auto  
  --execute


使用pt-online-schema-change能夠跳過鎖表的坑




爲了保持兩張表的數據一致性,拷貝的那部分數據須要上鎖,使用共享鎖share_mode來鎖行,能夠經過show full processlist看到一次大概對10萬行,每次拷貝1秒不到


 INSERT LOW_PRIORITY IGNORE INTO `myshard`.`_tbl_immsg_bigo_128_new` (`sid`, `tm_timestamp`, `tm_lasttime`, `gid`, `group_name`, `default_flag`, `group_attr`, `group_owner`, `group_extension`, `is_del`, `app_id`, `mic_seat`, `invite_perm`, `invite_media_perm`, `pub_id_search`, `apply_verify`, `public_id`, `introduc`, `family_id`, `__version`, `__deleted`) SELECT `sid`, `tm_timestamp`, `tm_lasttime`, `gid`, `group_name`, `default_flag`, `group_attr`, `group_owner`, `group_extension`, `is_del`, `app_id`, `mic_seat`, `invite_perm`, `invite_media_perm`, `pub_id_search`, `apply_verify`, `public_id`, `introduc`, `family_id`, `__version`, `__deleted` FROM `myshard`.`tbl_immsg_bigo_128` FORCE INDEX(`PRIMARY`) WHERE ((`sid` >= '2112908055')) AND ((`sid` <= '2112916949')) LOCK IN SHARE MODE /*pt-online-schema-change 119079 copy nibble*/



原本使用碎片整理是由於磁盤使用率96%,但碎片整理時發現磁盤使用率變成99%,差點就爆了

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        58G  2.7G   53G   5% /
tmpfs         24G     0   24G   0% /dev/shm
/dev/sda1       485M   32M  428M   7% /boot
/dev/sda5       1.6T  452G  1.1T  31% /data
/dev/sdb1       1.3T  1.2T   25G  99% /data1


這是由於在把舊錶拷貝到臨時表的時,會把表數據複製一份數據,10G的表,可能複製出來是7G,這個過程磁盤會快速消耗,不當心就會把磁盤撐滿形成數據丟失了


爲了不這個坑,應該把整個數據庫的表,按照體積從小到大排序,而且把索引文件,表結構去掉,爲了方便顯示出體積,這裏加了一個l參數,其實是不加的,只獲取表名字,而後重定向一個文件裏,碎片整理就按照這個順序

ls -lSr --ignore="*.frm"
-rw-rw---- 1 mysql mysql   4096 Jul 25 12:33 tables_priv.MYI
-rw-rw---- 1 mysql mysql   4096 Jul 25 12:33 procs_priv.MYI
-rw-rw---- 1 mysql mysql   4096 Jul 25 12:33 columns_priv.MYI
-rw-rw---- 1 mysql mysql   5120 Jul 25 12:33 proxies_priv.MYI
-rw-rw---- 1 mysql mysql   5120 Jul 25 12:43 db.MYI
-rw-rw---- 1 mysql mysql   8928 Jul 25 12:33 help_relation.MYD
-rw-rw---- 1 mysql mysql  16384 Jul 25 12:33 help_keyword.MYI
-rw-rw---- 1 mysql mysql  18432 Jul 25 12:33 help_relation.MYI
-rw-rw---- 1 mysql mysql  20480 Jul 25 12:33 help_topic.MYI
-rw-rw---- 1 mysql mysql  22078 Jul 25 12:33 help_category.MYD
-rw-rw---- 1 mysql mysql  89241 Jul 25 12:33 help_keyword.MYD
-rw-rw---- 1 mysql mysql 419392 Jul 25 12:33 help_topic.MYD


能夠寫一個腳本,統計每一個表整理的時間,整理先後的體積比較,效果以下


正在對錶tbl_immsg_bigo_128進行碎片整理...第9張,還剩93張
+----------------------------+----------+----------+-------------------------------------------------------------------+
| Table                      | Op       | Msg_type | Msg_text                                                          |
+----------------------------+----------+----------+-------------------------------------------------------------------+
| myshard.tbl_immsg_bigo_128 | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| myshard.tbl_immsg_bigo_128 | optimize | status   | OK                                                                |
+----------------------------+----------+----------+-------------------------------------------------------------------+
表:tbl_immsg_bigo_128, 整理前:3373M, 整理後:2729M, 節省空間:-644M,耗時:143秒
----------------------------------------------------------------------------------------------
正在對錶tbl_immsg_bigo_132進行碎片整理...第10張,還剩92張
+----------------------------+----------+----------+-------------------------------------------------------------------+
| Table                      | Op       | Msg_type | Msg_text                                                          |
+----------------------------+----------+----------+-------------------------------------------------------------------+
| myshard.tbl_immsg_bigo_132 | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| myshard.tbl_immsg_bigo_132 | optimize | status   | OK                                                                |
+----------------------------+----------+----------+-------------------------------------------------------------------+
表:tbl_immsg_bigo_132, 整理前:3541M, 整理後:2889M, 節省空間:-652M,耗時:153秒


所有表整理完之後,96%的空間,碎片整理完後變成85%,騰出130G的空間

相關文章
相關標籤/搜索