MySQL DROP TABLE操做以及 DROP 大表時的注意事項

語法: node

刪表 mysql

[sql]  view plain copy
  1. DROP TABLE Syntax  
  2. DROP [TEMPORARYTABLE [IF EXISTS]  
  3.     tbl_name [, tbl_name] ...  
  4.     [RESTRICT | CASCADE]  

可一次刪除一張或多張表。需具備所刪除表上的DROP權限。表定義文件和數據文件均被移除。表被刪除後表上的用戶權限不會被自動刪除。參數裏表中指定的表名不存在則報錯,但對於存在的表仍會刪除。可經過指定IF EXISTS阻止表不存在時引起的錯誤(此時對於不存在的表僅產生一個NOTE)。對於分區表,除了移除表定義,分區、數據外還移除與之關聯的分區定義文件(.par)。在MySQL5.6中參數[RESTRICT | CASCADE]不作任何事情。[TEMPORARY] 關鍵字代表只刪臨時表,語句不會結束正在進行的事務(MySQL中DDL語句會隱式提交),不會進行權限檢查。 sql


刪庫
[sql]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. DROP DATABASE Syntax  
  2. DROP {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 刪除。

刪除大表的注意事項
對於表的刪除,由於InnoDB引擎會在table cache層面維護一個全局獨佔鎖一直到DROP TABLE完成爲止,這樣,對於表的其餘操做會被HANG住。對於較大的表來講,DROP TABLE操做可能須要很長的時間,所以須要一種有效的辦法來提高大表的刪除速度,以儘量下降HANG住的時間。能夠經過設置硬連接來達到此目的。
好比有一個樣例表:
example_table

使用InnoDB引擎且指定innodb_file_per_table=ON時在數據目錄中與該表對應的有以下兩個文件,分別爲表定義文件和數據文件。
[plain]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. sudo ls  -lh /data/mysql/testdb  
  2. -rw-rw---- 1 mysql mysql 8.4K Oct 28 13:26 example_table.frm  
  3. -rw-rw---- 1 mysql mysql 100G Oct 28 13:26 example_table.ibd  
該表有100G這麼大,直接使用DROP TABLE來完成刪表動做,那麼這條語句要執行很長時間。此時即可以經過在該表對應的數據文件上設置硬連接來進行刪除。
[plain]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. sudo ln /data/mysql/testdb/example_table.ibd /data/mysql/testdb/example_table.ibd.hdlk  
  2. sudo ls  -lh /data/mysql/testdb  
  3. -rw-rw---- 1 mysql mysql 8.4K Oct 28 13:26 example_table.frm  
  4. -rw-rw---- 2 mysql mysql 100G Oct 28 13:26 example_table.ibd  
  5. -rw-rw---- 2 mysql mysql 100G Oct 28 13:26 example_table.ibd.hdlk  
發現多了一個example_table.ibd.hdlk文件,且example_table.ibd.hdlk和example_table.ibd的innode均爲2。也即當有多個文件名(如硬連接)指向同一innode時,這個innode的引用數大於1,此時,刪除其中任何一個文件名都只會刪除指向innode的指針而並不會直接刪除物理文件塊,所以會很是快,直至innode的引用計數等於1時纔會真正刪除對應的物理文件塊,真正刪除物理文件塊時纔會比較耗時。

在創建了硬連接後再執行DROP TABLE操做:
[sql]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. DROP TABLE example_table;  
發現會很快的完成,查看對應的表定義和數據文件:
[plain]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. sudo ls  -lh /data/mysql/testdb  
  2. -rw-rw---- 1 mysql mysql 100G Oct 28 13:26 example_table.ibd.hdlk  
只剩下example_table.ibd.hdlk,且innode的引用計數變爲了1。也即剛纔的DROP TABLE操做實施刪除了物理文件的一個指針example_table.ibd ,於是很是快。

剩下的任務就是刪除真正的物理文件了,由於此時innode的引用計數已經變爲了1,直接刪除example_table.ibd.hdlk便會真正的刪除物理文件。但由於物理文件較大,刪除大文件仍會引發較高的磁盤IO開銷。所以可使用少許逐次刪除的方式來刪除大的數據文件。truncate工具能夠用於增長或縮減指定文件的尺寸,能夠用於此目的:
[plain]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. for i in `seq 100 -1 1 ` ;do sleep 2;sudo truncate -s ${i}G /data/mysql/testdb/example_table.ibd.hdlk;done  
  2. sudo rm -rf /data/mysql/testdb/example_table.ibd.hdlk;  
從100G開始,每次縮減1G,停2秒,繼續,直到文件只剩1G,最後使用rm命令刪除剩餘的部分。

對於整個數據庫的刪除能夠先刪除其中較大的表,最後在執行DROP DATABASE刪除整個庫,對大表的刪除可參見上面的方法。
相關文章
相關標籤/搜索