mysql刪除大表更快的drop table
在DROP TABLE的時候,所有程序不管是DDL還是DML都被HANG起;直到DROP結束才繼續執行;
這是因為INNODB會維護一個全域性獨佔鎖(在table cache上面),直到DROP TABLE完成才釋放。
在我們常用的ext3,ext4,ntfs檔案系統,要刪除一個大檔案(幾十G,甚至幾百G)還是需要點時間的。
下面我們介紹一個快速DROP table 的方法; 不管多大的表,INNODB 都可以很快返回,表刪除完成;
眾所周知drop table會嚴重的消耗伺服器IO效能,如果被drop的表容量較大,甚至會影響到線上的正常。
首先,我們看一下為什麼降容量大的表會影響線上服務
直接執行drop table,MySQL會將表定義和表資料全都刪除,包括磁碟上的物理檔案,也包括緩衝池中的記憶體資料。
這麼分兩步,第一步從緩衝池中刪除,這會涉及到table_cache的鎖,如果持有table_cache的鎖,這將導致其他查詢都無法執行。這種情況在沒有innodb_per_table之前尤為嚴重。另外,mysql5.5.23之後新增lazy drop table功能,這個功能用來解決互斥的LRU列表。其中心思想就是加鎖,找到需要被刪除的頁面,刪除1024個頁之後釋放鎖讓其他執行緒工作,之後迴圈而percona的lazy drop處理起來更優雅一些,其會先加鎖,然後找到需要被刪除的頁面,標記,釋放鎖,後臺慢慢刪除。
之後就是第二步,這步在大容量表的時候更為消耗時間,那就是在OS上刪除物理檔案。大家都知道在EXT3上RM一個200G的檔案會非常耗時,這是由於EXT3儲存資料的結構導致,如果一個很大的檔案,EXT3的i_block無法直接存放,需要多層巢狀才能完全儲存下,在這種情況下由於對映的層次多,並且由於多層對映也不會是順序儲存的,就導致了很大的隨機IO,這就導致了刪除物理檔案非常慢的現象。在這種情況下,建議升級到EXT4,這是由於EXT4比ext3的使用程度分配儲存空間,其最大的優勢就是順序儲存。
EXT3:
EXT4:
知道了原因,我們來說說如何解決具體步驟如下:
1,建立硬連結。
ln table.ibd table.idb.hdlk
2,mysql執行drop table操作。
drop table if exists tablename;
3,使用截斷刪除物理檔案。
truncate -s 1024 * 1024 * 4 filename
其實硬連結和drop table就不用多說了,在建立硬連結之後,mysql會認為rm了硬連結檔案之後就算操作完畢,不會真正去刪除物理檔案從而提高了速度。但是對於伺服器來說,實際的物理檔案還在,如果手動RM,還是會產生很多的IO影響,這時候就用到了截斷這個工具。這個工具會根據指定的尺寸大小進行逐步刪除,會將對IO造成的影響降到最低。
用法:truncate OPTION ... FILE ...
縮小或擴充套件每個FILE的大小到指定的大小
建立不存在的FILE引數。
如果檔案大於指定的大小,則額外的資料將丟失。
如果檔案較短,則延長部分(孔)
讀為零位元組。
長期期權的
強制性論據也適用於 短期期權。
-c,–no建立 做不建立任何檔案
-o,–io- 塊對待SIZE作為IO塊而不是位元組數
-r,–reference = 上的RFile的RFile基底大小
-s,–size = SIZE通過SIZE設定或調整檔案大小
- 幫助顯示此幫助和退出
- 版本輸出版本資訊並退出
SIZE可以是(或可以是可選的後面的整數)以下之一:對於G,T,P,E,Z,Y,
KB 1000,K 1024,MB 1000 * 1000,M 1024 * 1024等。
SIZE也可以字首為以下修改字元之一:
</span> + <span style="color:rgb(128,0,0);line-height:1.5 !important;">' </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">延伸,
- ‘減少,< <span style="color:rgb(128,0,0);line-height:1.5 !important;">' </span><span style="color:rgb(128,0,0);line-height:1.5 !important;">至多,
> ’ 至少,
` / ’ 迴圈到多個,’%’ 輪到多個。
報告截斷bug - [email protected]
GNU coreutils主頁: http:// www.gnu.org/software/coreutils/>
一般幫助使用GNU軟體:<http:// www.gnu.org/gethelp/>
有關完整的文件,請執行:info coreutils ’ 截斷呼叫“
[email protected] : test 21:39:34> drop table tt ;
Query OK, 0 rows affected (25.01 sec)
刪除一個11G的表用時25秒左右(硬體不同,時間不同);
下面我們來對另一個更大的表進行刪除;
但之前,我們需要對這個表的資料檔案做一個硬連線:
[email protected] # ln stock.ibd stock.id.hdlk
[email protected] # ls stock.* -l
-rw-rw—- 1 MySQL mysql 9196 Apr 14 23:03 stock.frm
-rw-r–r– 2 mysql mysql 19096666112 Apr 15 09:55 stock.ibd
-rw-r–r– 2 mysql mysql 19096666112 Apr 15 09:55 stock.id.hdlk
你會發現stock.ibd的INODES屬性變成了2;
[email protected] : test 21:39:34> drop table stock ;
Query OK, 0 rows affected (0.99 sec)
1秒不到就刪除完成; 也就是DROP TABLE不用再HANG這麼久了。
但table是刪除了,資料檔案還在,所以你還需要最後資料檔案給刪除。
root # ll
total 19096666112
-rw-r–r– 2 mysql mysql 19096666112 Apr 15 09:55 stock.id.hdlk
root # rm stock.id.hdlk
雖然DROP TABLE 多繞了幾步。(如果你有一個比較可靠的自執行程式(自動為大表建立硬連結,並會自動刪除過期的硬連結檔案),就會顯得不那麼繁瑣。)
這樣做能大大減少MYSQL HANG住的時間; 相信還是值得的。
至於原理: 就是利用OS HARD LINK的原理,
當多個檔名同時指向同一個INODE時,這個INODE的引用數N>1, 刪除其中任何一個檔名都會很快.
因為其直接的物理檔案塊沒有被刪除.只是刪除了一個指標而已;
當INODE的引用數N=1時, 刪除檔案需要去把這個檔案相關的所有資料塊清除,所以會比較耗時;
<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
if(typeof window.localStorage === "object" && typeof window.csdn.anonymousUserLimit === "object"){
if(!window.csdn.anonymousUserLimit.judgment()){
window.csdn.anonymousUserLimit.Jumplogin();
return false;
}else if(!currentUserName){
window.csdn.anonymousUserLimit.updata();
}
}
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>