同事小姐姐:MySQL刪除數據我到底該用哪種方式 ?

上週四下班後我正在工位上梳理一些文檔,同事小姐姐阿僑來找我,“哈哥,晚上有空麼?”

“嗯?是不是你家冰箱又壞了,讓我過去修冰箱啊。”(宿舍跟小姐姐住的很近,前段時間去她家幫她修過冰箱)

“哪有,我遇到了一件怪事兒,你來幫我看看嘛~”,阿僑說。

“看完再去你家修冰箱麼?”

阿僑:。。。。。。。。

 

 

過一會兒我來到小姐姐工位上,她說:“哈哥你看,我發現MySQL有bug,我下午爲了清理磁盤,明明刪除了100萬條MySQL數據,磁盤不僅沒有變小,反而更滿了呢??”

那你是怎麼刪除的?

“delete from table 呀”

“怪不得,其實要刪除MySQL數據是有好幾種方式的,有些場景下是不應該用DELETE的,比如你這種情況。好了,讓我來給你講一下吧。”

 

MySQL刪除數據的方式都有哪些?

咱們常用的三種刪除方式:通過 delete、truncate、drop 關鍵字進行刪除;這三種都可以用來刪除數據,但場景不同。

一、從執行速度上來說

drop > truncate >> DELETE


二、從原理上講

1、DELETE

DELETE from TABLE_NAME where xxx

1、DELETE屬於數據庫DML操作語言,只刪除數據不刪除表的結構,會走事務,執行時會觸發trigger;

2、在 InnoDB 中,DELETE其實並不會真的把數據刪除,mysql 實際上只是給刪除的數據打了個標記爲已刪除,因此 delete 刪除表中的數據時,表文件在磁盤上所佔空間不會變小,存儲空間不會被釋放,只是把刪除的數據行設置爲不可見。雖然未釋放磁盤空間,但是下次插入數據的時候,仍然可以重用這部分空間(重用 → 覆蓋)。

3、DELETE執行時,會先將所刪除數據緩存到rollback segement中,事務commit之後生效;

4、delete from table_name刪除表的全部數據,對於MyISAM 會立刻釋放磁盤空間,InnoDB 不會釋放磁盤空間;

5、對於delete from table_name where xxx 帶條件的刪除, 不管是InnoDB還是MyISAM都不會釋放磁盤空間;

6、delete操作以後使用 optimize table table_name 會立刻釋放磁盤空間。不管是InnoDB還是MyISAM 。所以要想達到釋放磁盤空間的目的,delete以後執行optimize table 操作。

示例:查看錶佔用硬盤空間大小的SQL語句如下:(用M做展示單位,數據庫名:csjdemo,表名:demo2)

select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') as table_size 
   from information_schema.tables 
      where table_schema='csjdemo' AND table_name='demo2';

然後執行空間優化語句,以及執行後的表Size變化:

optimize table demo2


再看看這張表的大小,就只剩下表結構size了。

7、delete 操作是一行一行執行刪除的,並且同時將該行的的刪除操作日誌記錄在redo和undo表空間中以便進行回滾(rollback)和重做操作,生成的大量日誌也會佔用磁盤空間

2、truncate

Truncate table TABLE_NAME

1、truncate:屬於數據庫DDL定義語言,不走事務,原數據不放到 rollback segment 中,操作不觸發 trigger。

執行後立即生效,無法找回
執行後立即生效,無法找回
執行後立即生效,無法找回

2、truncate table table_name 立刻釋放磁盤空間 ,不管是 InnoDB和MyISAM 。truncate table其實有點類似於drop table 然後creat,只不過這個create table 的過程做了優化,比如表結構文件之前已經有了等等。所以速度上應該是接近drop table的速度;

3、truncate能夠快速清空一個表。並且重置auto_increment的值。

但對於不同的類型存儲引擎需要注意的地方是:

  • 對於MyISAM,truncate會重置auto_increment(自增序列)的值爲1。而delete後表仍然保持auto_increment。
  • 對於InnoDB,truncate會重置auto_increment的值爲1。delete後表仍然保持auto_increment。但是在做delete整個表之後重啓MySQL的話,則重啓後的auto_increment會被置爲1。

也就是說,InnoDB的表本身是無法持久保存auto_increment。delete表之後auto_increment仍然保存在內存,但是重啓後就丟失了,只能從1開始。實質上重啓後的auto_increment會從 SELECT 1+MAX(ai_col) FROM t 開始。

4、小心使用 truncate,尤其沒有備份的時候,如果誤刪除線上的表,記得及時聯繫中國民航,訂票電話:400-806-9553


3、drop

Drop table Tablename

1、drop:屬於數據庫DDL定義語言,同Truncate;

執行後立即生效,無法找回
執行後立即生效,無法找回
執行後立即生效,無法找回

2、drop table table_name 立刻釋放磁盤空間 ,不管是 InnoDB 和 MyISAM; drop 語句將刪除表的結構被依賴的約束(constrain)、觸發器(trigger)、索引(index);  依賴於該表的存儲過程/函數將保留,但是變爲 invalid 狀態。

3、小心使用 drop ,要刪表跑路的兄弟,請在訂票成功後在執行操作!訂票電話:400-806-9553


可以這麼理解,一本書,delete是把目錄撕了,truncate是把書的內容撕下來燒了,drop是把書燒了

 

故事續接上文:

阿僑才反應過來,“這下我算明白這事兒的原因了。”

我微微一笑摸了摸阿僑的頭,見她一臉崇拜的目光。我突然意識到了什麼,決定晚上要請她喫個飯。然後嘿嘿嘿。

話還沒開口,她接了個電話說,“哈哥,我男朋友接我喫飯去,我先撤啦,剩下的你幫我處理一下哈。”

我.......

 

 

第二天中午,一陣急促的聲音,“哈哥哈哥,你快來幫我看一下。”

阿僑:“我 drop 刪錯表了”。

我一樂,“等我打完這把王者農藥給你看看,昨天不是跟你說了,drop沒法回滾~”

鈴鈴鈴,電話響了,接通老闆說道:“小陳,咱們線上平臺咋沒數據了?可別讓客戶看到啊,你抓緊處理一下!”

我艹,我一看,“阿僑,你他孃的刪的哪張表啊!!把我線上庫表刪啦。趕緊給我訂機票”。

她一臉緊張和羞愧的看着我,寄希望於我能搞定她惹的禍,連連道歉。

“行吧,我處理一下吧,要是能處理好記得請我喫飯啊!”,她連連點頭。

等她離開後,我默默打開每天自動執行的數據庫表備份文件目錄,重新導了一份昨天晚上的備份數據,深藏功與名。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章