最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL數(shù)據(jù)清除三劍客之DROP、DELETE與TRUNCATE深度對比指南

 更新時(shí)間:2026年05月08日 09:36:57   作者:霖霖總總  
這篇文章主要介紹了MySQL數(shù)據(jù)清除三劍客之DROP、DELETE與TRUNCATE深度對比的相關(guān)資料,DROP、DELETE和TRUNCATE命令都可以用于刪除MySQL數(shù)據(jù)庫中的數(shù)據(jù),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在 MySQL 數(shù)據(jù)庫的日常運(yùn)維與開發(fā)中,DROP、DELETETRUNCATE 是三種常用于“清除數(shù)據(jù)”的 SQL 語句。

然而,它們在實(shí)現(xiàn)機(jī)制、事務(wù)行為、性能表現(xiàn)及適用場景上存在根本性差異。

一、語法與基本語義

語句語法示例作用對象語義說明
DELETEDELETE FROM table_name [WHERE ...];表中的行逐行刪除滿足條件的記錄(若無 WHERE,則刪除全部行)
TRUNCATETRUNCATE TABLE table_name;整張表快速清空表中所有數(shù)據(jù),重置自增計(jì)數(shù)器(若存在)
DROPDROP TABLE table_name;表結(jié)構(gòu)本身刪除整張表(包括結(jié)構(gòu)、索引、權(quán)限等元數(shù)據(jù))

注意:TRUNCATEDROP 是 DDL(Data Definition Language),而 DELETE 是 DML(Data Manipulation Language)。

二、核心維度對比

DELETE、TRUNCATE 與 DROP:MySQL 數(shù)據(jù)清除操作全對比

維度DELETETRUNCATEDROP
語句類型DMLDDLDDL
是否可帶 WHERE? 是? 否? 否
事務(wù)性? 可回滾(在事務(wù)中)? 隱式提交,不可回滾? 隱式提交,不可回滾
觸發(fā)器? 觸發(fā) DELETE 觸發(fā)器? 不觸發(fā)? 不觸發(fā)
寫 Redo/Undo Log? 寫 Undo(支持回滾)+ Redo? 不寫 Undo;部分 Redo(元數(shù)據(jù))? 不寫 Undo;寫 Redo(元數(shù)據(jù))
鎖粒度行鎖(InnoDB)表級元數(shù)據(jù)鎖(MDL)表級元數(shù)據(jù)鎖(MDL)
自增列重置? 不重置? 重置為初始值(通常為1)? 表被刪除,自然重置
空間回收? 標(biāo)記刪除,空間由 purge 線程異步回收? 立即釋放表空間(InnoDB)? 刪除.ibd文件,立即釋放磁盤空間
執(zhí)行速度慢(逐行處理)快(重建表)快(刪除文件)

注:在 MyISAM 引擎中,TRUNCATE 行為類似 DROP + CREATE,但 InnoDB 自 5.7 起已優(yōu)化為原地重建(instant truncate)。

DELETE、TRUNCATE 與 DROP 對性能的影響對比

維度DELETETRUNCATEDROP
執(zhí)行機(jī)制逐行掃描、標(biāo)記刪除(邏輯刪除),寫入 Undo Log 和 Redo Log刪除原表數(shù)據(jù)文件,重建空表結(jié)構(gòu)(物理清空)刪除表的元數(shù)據(jù)及物理文件(.frm/.ibd),徹底移除表
I/O 開銷高:每行都要寫 Undo + Redo,大量隨機(jī) I/O極低:僅元數(shù)據(jù)操作 + 文件截?cái)?重建,順序 I/O極低:直接刪除文件,少量元數(shù)據(jù)日志寫入
事務(wù)日志增長顯著:Undo Log 可能非常大(尤其全表刪除)幾乎無:不生成行級 Undo,僅少量 DDL Redo無 Undo;僅寫入 DDL 相關(guān) Redo(用于崩潰恢復(fù))
鎖競爭行鎖 + 可能升級為間隙鎖,長時(shí)間運(yùn)行易阻塞其他事務(wù)短暫表級元數(shù)據(jù)鎖(MDL),通常毫秒級完成短暫表級元數(shù)據(jù)鎖(MDL),持有時(shí)間略長于 TRUNCATE(因涉及字典操作)
空間回收延遲:由后臺(tái) Purge 線程異步回收,可能造成“表膨脹”立即:.ibd 文件被截?cái)嗷蛑亟?,磁盤空間即時(shí)釋放立即:.ibd.frm(或數(shù)據(jù)字典記錄)被刪除,磁盤空間完全釋放
適用數(shù)據(jù)量小到中等規(guī)模(建議 < 10 萬行)任意規(guī)模(百萬/億級均可高效處理)任意規(guī)模,但僅適用于不再需要該表的場景
是否可回滾? 是(在事務(wù)中)? 否(隱式提交)? 否(隱式提交)
對自增列影響不重置(下次插入繼續(xù)遞增)重置為初始值(如 1)表被刪除,自增信息隨之消失
觸發(fā)器/外鍵觸發(fā) DELETE 觸發(fā)器;受外鍵約束影響不觸發(fā)觸發(fā)器;若存在外鍵引用則失敗不觸發(fā)觸發(fā)器;自動(dòng)解除外鍵依賴(因表已不存在)

為什么truncate和drop不產(chǎn)生undo log,卻會(huì)產(chǎn)生redo log

1. 核心結(jié)論

DROP 和 TRUNCATE 雖然不寫入“行數(shù)據(jù)”的 Redo Log,但會(huì)寫入“元數(shù)據(jù)變更”的 Redo Log,目的是確保:

  • 在數(shù)據(jù)庫崩潰后能正確恢復(fù)表結(jié)構(gòu)狀態(tài)(如:表是否還存在);
  • 保證 DDL 操作的原子性與持久性(ACID 中的 Durability)。

這與 DELETE 寫入“行級 Redo”有本質(zhì)區(qū)別。

2. Redo Log 的作用回顧

InnoDB 的 Redo Log 主要用于:

  • 記錄 物理頁(Page)的變更;
  • 在 crash recovery 時(shí)重做(replay)這些變更,使數(shù)據(jù)庫回到崩潰前的一致狀態(tài);
  • 只記錄“做了什么”,不記錄“如何撤銷”(Undo Log 才負(fù)責(zé)回滾)。

因此:

  • DML(如 DELETE)修改了數(shù)據(jù)頁 → 必須寫 Redo;
  • DDL 修改了數(shù)據(jù)字典(Data Dictionary)或文件系統(tǒng)結(jié)構(gòu) → 也必須寫 Redo,否則崩潰后無法知道“表是否已被刪除”。

3. 為什么DROP/TRUNCATE不寫“行級 Redo”?

因?yàn)樗鼈?/strong>不逐行修改數(shù)據(jù)頁**!**

操作是否修改數(shù)據(jù)頁內(nèi)容?是否需要行級 Redo?
DELETE? 是(標(biāo)記刪除位、更新鏈)? 需要
TRUNCATE? 否(直接釋放/重建整個(gè)表空間)? 不需要
DROP? 否(刪除整個(gè) .ibd 文件)? 不需要
  • TRUNCATE 在 InnoDB 中本質(zhì)是 “丟棄舊表空間 + 創(chuàng)建新空表空間”
  • DROP“從數(shù)據(jù)字典移除表元數(shù)據(jù) + 刪除 .ibd 文件”;
  • 兩者都不遍歷或修改原有數(shù)據(jù)行,因此無需記錄每行的 Redo。

4.那它們寫的是什么 Redo?

它們寫的是 “元數(shù)據(jù)操作”的 Redo Log,主要包括:

(1)數(shù)據(jù)字典(Data Dictionary)變更

MySQL 8.0 將數(shù)據(jù)字典完全存儲(chǔ)在 InnoDB 表中(如 tables等)。
執(zhí)行 DROP TABLE t 時(shí),InnoDB 會(huì):

  • tables 中刪除對應(yīng)記錄;
  • 這個(gè)刪除操作本身就是一個(gè) DML,會(huì)生成 Redo Log!

所以:雖然用戶表的數(shù)據(jù)沒寫 Redo,但系統(tǒng)表的變更寫了 Redo。

(2)表空間(Tablespace)元信息變更

  • TRUNCATE 會(huì)分配新的表空間 ID 或重置空間頭;
  • DROP 會(huì)標(biāo)記表空間為“可刪除”并在 purge 階段清理;
  • 這些操作涉及 InnoDB 系統(tǒng)頁(如 FSP_HDR、IBUF_BITMAP)的修改,也會(huì)產(chǎn)生 Redo。

(3)DDL 日志(DDL Log Table)

MySQL 8.0 引入了 原子 DDL 機(jī)制,使用一張隱藏的 mysql.innodb_ddl_log 表(臨時(shí)表)記錄 DDL 步驟。
例如 DROP TABLE 可能包含:

1. 刪除索引
2. 刪除表數(shù)據(jù)字典記錄
3. 刪除 .ibd 文件

每一步都記錄到 innodb_ddl_log,而該表的插入/刪除操作同樣會(huì)寫 Redo Log,確保崩潰后能回放或回滾整個(gè) DDL。

可通過 SELECT * FROM mysql.innodb_ddl_log;(需 SUPER 權(quán)限)查看(通常為空,因操作完成后自動(dòng)清理)。

5. 崩潰恢復(fù)時(shí)如何工作?

假設(shè)在 DROP TABLE t 執(zhí)行到一半時(shí) MySQL 崩潰:

  1. 重啟時(shí),InnoDB 進(jìn)行 crash recovery,重放 Redo Log;
  2. Redo 中包含:
    • mysql.tables 的刪除記錄;
    • innodb_ddl_log 的寫入;
  3. 若 DDL 未完成,InnoDB 會(huì)根據(jù) innodb_ddl_log 自動(dòng)回滾或完成剩余步驟(原子 DDL 保證);
  4. 最終結(jié)果:要么表完全存在,要么完全不存在——不會(huì)出現(xiàn)“半刪除”狀態(tài)。

6. 對比總結(jié)

特性DELETETRUNCATE / DROP
修改用戶數(shù)據(jù)頁?? 是? 否
寫行級 Redo?? 是? 否
修改系統(tǒng)表(數(shù)據(jù)字典)?? 否? 是
寫元數(shù)據(jù) Redo?? 否? 是
支持事務(wù)回滾?? 是(靠 Undo)? 否(但崩潰可恢復(fù)一致性)
崩潰后能否保證狀態(tài)一致?? 能? 能(靠 DDL Redo + 原子 DDL)

總結(jié):

DROP 和 TRUNCATE 之所以“僅寫入 DDL 相關(guān) Redo”,是因?yàn)樗鼈儾恍薷挠脩魯?shù)據(jù)行,但必須持久化“表結(jié)構(gòu)是否還存在”這一元數(shù)據(jù)狀態(tài)。
這些 Redo 記錄的是對 InnoDB 數(shù)據(jù)字典表表空間元信息 的變更,用于在崩潰恢復(fù)時(shí)確保 DDL 操作的原子性與持久性,而非用于恢復(fù)被刪除的數(shù)據(jù)內(nèi)容。

這也是為什么:你可以從崩潰中恢復(fù)出“表是否被刪”的正確狀態(tài),但無法恢復(fù)被 DROP 或 TRUNCATE 刪除的數(shù)據(jù)本身——因?yàn)閿?shù)據(jù)頁從未被 Redo 記錄過。

三、內(nèi)部處理流程

該流程圖展示了 InnoDB 引擎下三種操作的核心路徑。注意:DELETE 是唯一支持回滾的操作。

四、典型使用場景建議

  • 使用 DELETE

    • 需要按條件刪除部分?jǐn)?shù)據(jù);
    • 要求操作可回滾(如在事務(wù)中);
    • 存在 ON DELETE CASCADE 外鍵依賴;
    • 需要觸發(fā) DELETE 觸發(fā)器。
  • 使用 TRUNCATE

    • 需要快速清空整張大表;
    • 不關(guān)心事務(wù)回滾;
    • 希望重置自增 ID;
    • 表無外鍵引用(否則會(huì)報(bào)錯(cuò))。
  • 使用 DROP

    • 表不再需要,需徹底移除;
    • 釋放磁盤空間是首要目標(biāo);
    • 重構(gòu)表結(jié)構(gòu)(常配合 CREATE 使用)。

安全提示:生產(chǎn)環(huán)境中,建議對 DROPTRUNCATE 設(shè)置 sql_safe_updates=1 或通過權(quán)限控制限制執(zhí)行。

sql_safe_updates參數(shù)解析

sql_safe_updates 是 MySQL 中的一個(gè)會(huì)話級系統(tǒng)變量,主要用于防止執(zhí)行沒有 WHERE 條件的 UPDATE 和 DELETE 語句,以避免意外的大規(guī)模數(shù)據(jù)修改。

主要作用
當(dāng) sql_safe_updates 設(shè)置為 ON(或 1)時(shí):

1. 限制 UPDATE 語句

  • 必須包含 WHERE 子句
  • WHERE 子句中必須使用索引列
  • 不能使用 LIMIT 子句(某些 MySQL 版本)

2. 限制 DELETE 語句

  • 必須包含 WHERE 子句
  • WHERE 子句中必須使用索引列
  • 不能使用 LIMIT 子句

五、優(yōu)化DELETE操作的數(shù)據(jù)清理流程

當(dāng)必須使用 DELETE(如按時(shí)間范圍清理日志表)時(shí),可采用以下策略避免性能災(zāi)難:

1.分批刪除(Chunked Deletion)

-- 示例:每次刪除 10,000 行,避免長事務(wù)和大 Undo
DELETE FROM logs
WHERE create_time < '2023-01-01'
ORDER BY id
LIMIT 10000;

在應(yīng)用層循環(huán)執(zhí)行,直到返回影響行數(shù)為 0。配合 SLEEP(0.1) 減少主從延遲。

2.使用主鍵或索引列排序

確保 ORDER BY 使用聚簇索引(如 InnoDB 的主鍵),避免全表掃描+臨時(shí)排序。

3.控制事務(wù)大小

  • 單次 DELETE 不要超過 innodb_log_file_size 的 1/4;

  • 可顯式提交每個(gè)批次:

    START TRANSACTION;
    DELETE ... LIMIT 10000;
    COMMIT; -- 避免 Undo Log 過大
    

4.避免在高峰期執(zhí)行

選擇業(yè)務(wù)低峰期,并監(jiān)控 Innodb_rows_deleted、Innodb_buffer_pool_pages_dirty 等指標(biāo)。

5.考慮歸檔替代刪除

對歷史數(shù)據(jù)先 INSERT INTO archive_table SELECT ...,再 DROP 原表分區(qū)(若使用分區(qū)表),效率更高。

“不要?jiǎng)h除舊數(shù)據(jù),而是保留新數(shù)據(jù)并拋棄舊容器” —— 這是處理海量歷史數(shù)據(jù)清理的高性能范式,尤其在分區(qū)表場景下,效率遠(yuǎn)超 DELETE。

6.調(diào)整 Purge 線程參數(shù)(高級)

innodb_purge_threads = 4        # 默認(rèn) 4,可增至 8(多核)
innodb_max_purge_lag = 100000   # 控制 DML 延遲

六、高頻面試題

Q1:TRUNCATE能回滾嗎?

:不能。TRUNCATE 是 DDL 操作,在 MySQL 中會(huì)隱式提交當(dāng)前事務(wù),因此無法回滾。

Q2:DELETE不加 WHERE 會(huì)鎖全表嗎?

:在 InnoDB 中,DELETE 仍使用行鎖,但會(huì)逐行加鎖,可能因鎖數(shù)量過多導(dǎo)致性能下降或鎖等待,但并非“表鎖”。

Q3:為什么TRUNCATE比DELETE快?

:因?yàn)?TRUNCATE 不逐行刪除,而是直接釋放數(shù)據(jù)頁并重建空表,不寫 Undo Log,也無需觸發(fā)觸發(fā)器或檢查外鍵。

Q4:DROP TABLE后還能恢復(fù)數(shù)據(jù)嗎?

:除非有備份或使用了企業(yè)級閃回功能(如 Percona 的 pt-archiver 或 binlog 回放),否則無法直接恢復(fù)。.ibd 文件已被刪除。

Q5:TRUNCATE會(huì)重置自增 ID 嗎?DELETE呢?

TRUNCATE 會(huì)重置;DELETE 不會(huì),即使刪除所有行,下次插入仍從上次最大 ID +1 開始。

總結(jié)

到此這篇關(guān)于MySQL數(shù)據(jù)清除三劍客之DROP、DELETE與TRUNCATE深度對比的文章就介紹到這了,更多相關(guān)MySQL數(shù)據(jù)清除DROP、DELETE與TRUNCATE內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mysql5.1.26安裝配置方法詳解

    mysql5.1.26安裝配置方法詳解

    這篇文章主要為大家詳細(xì)介紹了mysql安裝配置方法,圖文詳解MySQL5.1.26安裝步驟,感興趣的小伙伴們可以參考一下
    2016-06-06
  • mysql 8.0.12 winx64解壓版安裝圖文教程

    mysql 8.0.12 winx64解壓版安裝圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0.12 winx64解壓版安裝圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Mysql5.6啟動(dòng)內(nèi)存占用過高解決方案

    Mysql5.6啟動(dòng)內(nèi)存占用過高解決方案

    vps的內(nèi)存為512M,安裝好nginx,php等啟動(dòng)起來,mysql死活啟動(dòng)不起來看了日志只看到對應(yīng)pid被結(jié)束了,后跟蹤看發(fā)現(xiàn)是內(nèi)存不足被killed;mysql5.6啟動(dòng)內(nèi)存占用過高怎么辦呢,下面小編給大家解答下
    2016-09-09
  • SQL insert into語句寫法講解

    SQL insert into語句寫法講解

    這篇文章主要介紹了SQL insert into語句寫法講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 深入理解MySQL主從復(fù)制線程狀態(tài)轉(zhuǎn)變

    深入理解MySQL主從復(fù)制線程狀態(tài)轉(zhuǎn)變

    這篇文章主要給大家介紹了關(guān)于MySQL主從復(fù)制線程狀態(tài)轉(zhuǎn)變的相關(guān)資料,文中介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • MySQL?存儲(chǔ)引擎InnoDB最佳實(shí)踐

    MySQL?存儲(chǔ)引擎InnoDB最佳實(shí)踐

    InnoDB是一款兼顧高可靠性和高性能的通用存儲(chǔ)引擎,在MySQL8.0中默認(rèn)的存儲(chǔ)引擎是InnoDB,這篇文章主要介紹了MySQL存儲(chǔ)引擎InnoDB詳解,需要的朋友可以參考下
    2025-05-05
  • 一文弄懂MySQL索引創(chuàng)建原則

    一文弄懂MySQL索引創(chuàng)建原則

    在關(guān)鍵字段的索引上建與不建索引,查詢速度相差近100倍,但差的索引和沒有索引效果一樣,索引并非越多越好,因?yàn)榫S護(hù)索引需要成本,下面這篇文章主要給大家介紹了關(guān)于MySQL索引創(chuàng)建原則的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • MySQL創(chuàng)建橫向直方圖的解決方案

    MySQL創(chuàng)建橫向直方圖的解決方案

    這篇文章主要給大家介紹了關(guān)于MySQL創(chuàng)建橫向直方圖的解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Mysql數(shù)據(jù)庫存儲(chǔ)過程基本語法講解

    Mysql數(shù)據(jù)庫存儲(chǔ)過程基本語法講解

    本文通過一個(gè)實(shí)例來給大家講述一下Mysql數(shù)據(jù)庫存儲(chǔ)過程基本語法,希望你能喜歡。
    2017-11-11
  • Windows7下Python3.4使用MySQL數(shù)據(jù)庫

    Windows7下Python3.4使用MySQL數(shù)據(jù)庫

    這篇文章主要為大家詳細(xì)介紹了Windows7下Python3.4使用MySQL數(shù)據(jù)庫,MySQL Community Server的安裝步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07

最新評論

商南县| 咸宁市| 米脂县| 郧西县| 来宾市| 海林市| 循化| 永顺县| 高邑县| 那曲县| 兰溪市| 东乌珠穆沁旗| 新津县| 南投市| 普洱| 邹城市| 高陵县| 汽车| 稷山县| 高安市| 黄石市| 招远市| 鹰潭市| 宁都县| 繁峙县| 安泽县| 乐亭县| 称多县| 同德县| 台北市| 永兴县| 潜山县| 富锦市| 礼泉县| 当阳市| 安远县| 克拉玛依市| 瑞金市| 潼关县| 徐州市| 祥云县|