概述
我們很多時候都會去drop一些大表,特别是生産環境做操作時,這裡主要提一些注意事項,僅供參考。
01
相關文法
1、删表
DROP TABLE SyntaxDROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name] ... [RESTRICT | CASCADE]
可一次删除一張或多張表。需具有所删除表上的DROP權限。表定義檔案和資料檔案均被移除。表被删除後表上的使用者權限不會被自動删除。參數裡表中指定的表名不存在則報錯,但對于存在的表仍會删除。可通過指定IF EXISTS阻止表不存在時引發的錯誤(此時對于不存在的表僅産生一個NOTE)。
對于分區表,除了移除表定義,分區、資料外還移除與之關聯的分區定義檔案(.par)。
在MySQL5.6中參數[RESTRICT | CASCADE]不做任何事情。[TEMPORARY] 關鍵字表明隻删臨時表,語句不會結束正在進行的事務(MySQL中DDL語句會隐式送出),不會進行權限檢查。
2、删庫
DROP DATABASE SyntaxDROP {DATABASE | SCHEMA} [IF EXISTS] db_name...
删除指定庫中的表之後删除庫。需具有庫上的DROP權限。庫被删除後庫上存在的使用者權限不會被自動删除。IF EXISTS用于阻止庫名不存在時引起的錯誤。庫被删除後預設庫會被重置。若在使用了符号連結的庫上執行DROP DATABASSE 連接配接和原始資料庫都會被删除。指令傳回被移除的表數量。
該指令會從指定的資料庫目錄中移除正常操作時MySQL自己産生的檔案和目錄,如:.BAK .DAT .HSH .MRG. MYD .MYI .TRG .TRN .db.frm .ibd .ndb .par,若存在db.opt也同樣會删除。若資料庫目錄中存在其他非MySQL本身産生的檔案或目錄,則整個資料庫目錄不會被移除。此時,需手動清理剩餘的檔案并重新運作DROP DATABASE語句。
删除資料庫并不會移除庫中建立的臨時表。臨時表在SESSION結束時自動被清理或者顯示的通過DROP TEMPORARY TABLE 删除。
02
删除大表的注意事項
對于表的删除,因為InnoDB引擎會在table cache層面維護一個全局獨占鎖一直到DROP TABLE完成為止,這樣,對于表的其他操作會被HANG住。對于較大的表來說,DROP TABLE操作可能需要很長的時間,是以需要一種有效的辦法來提升大表的删除速度,以盡可能降低HANG住的時間。這裡可以通過設定硬連結來達到此目的。
這裡用一個簡單實驗來測試一下:
1、建立測試表
表名:no_part_tab,1.8億資料量,表大小5.4G。
delimiter //CREATE PROCEDURE load_no_part_tab()begindeclare v int default 0; while v < 1000000 do insert into no_part_tab values (v,'testing partitions',adddate('1995-01-01',(rand(v)*36520) mod 3652)); set v = v + 1; end while; end //mysql> delimiter ;mysql> call load_no_part_tab();mysql> insert into no_part_tab select * from no_part_tab;.....mysql> create table t2 as select * from no_part_tab nologging;

使用InnoDB引擎且指定innodb_file_per_table=ON時在資料目錄中與該表對應的有如下兩個檔案,分别為表定義檔案和資料檔案。
2、drop table
直接使用DROP TABLE來完成删表動作,正常這條語句要執行很長時間。因為資料量隻有5G,是以不是很明顯。(這台伺服器空間不夠了,是以資料量沒加上去..)
3、建立硬連結
此時便可以通過在該表對應的資料檔案上設定硬連結來進行删除。
#ln /data/datafile/test/no_part_tab.MYD /data/datafile/test/no_part_tab.MYD.hdlk#ls -lh /data/datafile/test/
發現多了一個sys_user.ibd.hdlk檔案,且no_part_tab.MYD.hdlk和no_part_tab.MYD的innode均為2。也即當有多個檔案名(如硬連結)指向同一innode時,這個innode的引用數大于1,此時,删除其中任何一個檔案名都隻會删除指向innode的指針而并不會直接删除實體檔案塊,是以會非常快,直至innode的引用計數等于1時才會真正删除對應的實體檔案塊,真正删除實體檔案塊時才會比較耗時。
4、drop table
在建立了硬連結後再執行DROP TABLE操作:
DROP TABLE no_part_tab;
可以看到基本沒耗時,檢視對應的表定義和資料檔案:
隻剩下no_part_tab.MYD.hdlk,且innode的引用計數變為了1。也即剛才的DROP TABLE操作實施删除了實體檔案的一個指針no_part_tab,因而非常快。
5、删除真正的實體檔案
因為此時innode的引用計數已經變為了1,直接删除no_part_tab.MYD.hdlk便會真正的删除實體檔案。但因為實體檔案較大,删除大檔案仍會引起較高的磁盤IO開銷。是以可以使用少量逐次删除的方式來删除大的資料檔案。truncate工具可以用于增加或縮減指定檔案的尺寸,可以用于此目的:
#for i in `seq 6 -1 1 ` ;do sleep 2;sudo truncate -s ${i}G /data/datafile/test/no_part_tab.MYD.hdlk;done#rm -rf /data/datafile/test/no_part_tab.MYD.hdlk;
從6G開始,每次縮減1G,停2秒,繼續,直到檔案隻剩1G,最後使用rm指令删除剩餘的部分。
如果是整個資料庫的删除可以先删除其中較大的表,最後在執行DROP DATABASE删除整個庫,對大表的删除可參見上面的方法。
後面會分享更多devops和DBA方面的内容,感興趣的朋友可以關注下!