MySQL?中?truncate、delete、drop的區(qū)別詳解
DELETE、TRUNCATE、DROP 是 MySQL 中三種刪除數(shù)據(jù)的方式,核心區(qū)別如下:
| 對比維度 | DELETE | TRUNCATE | DROP |
|---|---|---|---|
| SQL 類型 | DML(數(shù)據(jù)操作語言) | DDL(數(shù)據(jù)定義語言) | DDL(數(shù)據(jù)定義語言) |
| 刪除內(nèi)容 | 表中的數(shù)據(jù)行 | 表中的所有數(shù)據(jù) | 表結(jié)構(gòu) + 數(shù)據(jù) + 索引 |
| WHERE 條件 | ? 支持 | ? 不支持 | ? 不支持 |
| 事務(wù)回滾 | ? 支持(需在事務(wù)中) | ? 不支持 | ? 不支持 |
| 觸發(fā)器 | ? 觸發(fā) AFTER/BEFORE | ? 不觸發(fā) | ? 不觸發(fā) |
| 自增 ID | 不重置 | ? 重置為初始值 | 表都沒了 |
| 執(zhí)行速度 | 慢(逐行刪除) | 快(直接清空) | 最快(直接刪除) |
| 空間釋放 | 不釋放,可復(fù)用 | ? 釋放頁空間 | ? 全部釋放 |
| 外鍵約束 | 受約束限制 | 需要先刪除外鍵 | 級聯(lián)刪除 |
一句話總結(jié):DELETE 是逐行刪除、可回滾;TRUNCATE 是整表清空、不可回滾、重置自增;DROP 是連表帶數(shù)據(jù)一起刪除。
深度解析
一、執(zhí)行機制對比

上圖展示了三種刪除方式的執(zhí)行機制差異:
- DELETE 逐行刪除:
- 掃描表的每一行,判斷是否滿足
WHERE條件 - 滿足條件的行標記為刪除,同時寫入
undo log用于回滾 - 每刪除一行都要更新索引、記錄日志
- 執(zhí)行速度慢,但支持條件過濾和事務(wù)回滾
- 掃描表的每一行,判斷是否滿足
- TRUNCATE 直接清空:
- 不逐行掃描,直接釋放數(shù)據(jù)頁(
DROP TABLE+CREATE TABLE的組合) - 重置
AUTO_INCREMENT計數(shù)器為初始值 - 不記錄
undo log,操作無法回滾 - 執(zhí)行速度極快,特別適合清空大表
- 不逐行掃描,直接釋放數(shù)據(jù)頁(
- DROP 刪除整表:
- 刪除表結(jié)構(gòu)(
.frm文件)、表數(shù)據(jù)(.ibd文件)、索引 - 表的元數(shù)據(jù)從數(shù)據(jù)字典中移除
- 依賴該表的視圖、存儲過程會失效
- 最徹底的刪除,表完全消失
- 刪除表結(jié)構(gòu)(
二、事務(wù)與回滾機制

關(guān)鍵差異:
- DELETE:
- 屬于 DML 操作,在事務(wù)中執(zhí)行
- 每刪除一行都記錄
undo log,可以通過ROLLBACK回滾 - 回滾時根據(jù)
undo log恢復(fù)數(shù)據(jù)
- TRUNCATE / DROP:
- 屬于 DDL 操作,執(zhí)行時會隱式提交當前事務(wù)
- 不記錄
undo log,操作后無法回滾 - 即使包裹在
BEGIN...ROLLBACK中也無效
重要提示:生產(chǎn)環(huán)境中 TRUNCATE 和 DROP 是高危操作,執(zhí)行前務(wù)必確認數(shù)據(jù)已備份!
三、自增 ID 處理差異
-- 測試表:當前最大 ID 為 5
CREATE TABLE test (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
INSERT INTO test (name) VALUES ('A'), ('B'), ('C'), ('D'), ('E');
-- 此時 AUTO_INCREMENT = 6
-- 場景一:使用 DELETE 刪除
DELETE FROM test; -- 刪除所有數(shù)據(jù)
INSERT INTO test (name) VALUES ('F');
-- id = 6(自增 ID 不重置,繼續(xù)遞增)
-- 場景二:使用 TRUNCATE 刪除
TRUNCATE TABLE test; -- 清空表
INSERT INTO test (name) VALUES ('F');
-- id = 1(自增 ID 重置為初始值)總結(jié):
DELETE:不重置AUTO_INCREMENT計數(shù)器TRUNCATE:重置AUTO_INCREMENT為初始值(通常是 1)
四、性能對比

性能結(jié)論:
- DELETE 最慢:需要逐行掃描、更新索引、記錄日志
- TRUNCATE 很快:直接釋放數(shù)據(jù)頁,相當于
DROP + CREATE - DROP 最快:直接刪除表的元數(shù)據(jù)和文件
五、使用場景選擇
-- ? 場景一:刪除部分數(shù)據(jù),需要條件過濾 DELETE FROM orders WHERE create_time < '2023-01-01'; -- ? 場景二:刪除數(shù)據(jù)后可能需要回滾 BEGIN; DELETE FROM temp_table WHERE status = 0; -- 檢查結(jié)果... ROLLBACK; -- 或者 COMMIT -- ? 場景三:清空大表,重置自增 ID,不需要回滾 TRUNCATE TABLE log_table; -- ? 場景四:徹底刪除表(包括結(jié)構(gòu)和數(shù)據(jù)) DROP TABLE deprecated_table; -- ? 場景五:刪除表但保留表結(jié)構(gòu) TRUNCATE TABLE user_temp; -- 推薦 -- 或者 DELETE FROM user_temp; -- 如果需要回滾
六、安全操作建議
-- ? 危險操作:生產(chǎn)環(huán)境禁止直接執(zhí)行 TRUNCATE TABLE orders; -- 數(shù)據(jù)無法恢復(fù)! DROP TABLE users; -- 表直接沒了! -- ? 安全操作:先備份再刪除 -- 步驟 1:創(chuàng)建備份表 CREATE TABLE orders_backup_20240101 AS SELECT * FROM orders; -- 步驟 2:確認備份無誤 SELECT COUNT(*) FROM orders_backup_20240101; -- 步驟 3:執(zhí)行刪除 TRUNCATE TABLE orders; -- ? 更安全的做法:使用事務(wù) + DELETE(小數(shù)據(jù)量) BEGIN; DELETE FROM orders WHERE create_time < '2023-01-01'; -- 檢查影響行數(shù) SELECT ROW_COUNT(); -- 確認無誤后提交 COMMIT; -- 或者回滾 ROLLBACK;
面試高頻追問
- TRUNCATE 為什么比 DELETE 快?
TRUNCATE是 DDL,直接釋放數(shù)據(jù)頁,不逐行刪除- 不記錄每行的
undo log,日志量極少 - 不觸發(fā)行級觸發(fā)器,不需要更新每行的索引
- 相當于
DROP TABLE+CREATE TABLE的組合
- DELETE 全表后空間會釋放嗎?
- 不會立即釋放,只是標記為 "可復(fù)用"
- 空間留給后續(xù)的
INSERT使用 - 如需釋放空間,可執(zhí)行
OPTIMIZE TABLE或ALTER TABLE ... ENGINE=InnoDB
- 如何恢復(fù)被 TRUNCATE 的數(shù)據(jù)?
- 正常情況下無法恢復(fù)(沒有
undo log) - 只能通過備份恢復(fù)(全量備份 + binlog 增量)
- 所以生產(chǎn)環(huán)境執(zhí)行前務(wù)必確認有備份
- 正常情況下無法恢復(fù)(沒有
- DELETE 會觸發(fā)觸發(fā)器嗎?
- 會觸發(fā)
BEFORE DELETE和AFTER DELETE觸發(fā)器 TRUNCATE不會觸發(fā)任何觸發(fā)器- 這也是
TRUNCATE更快的原因之一
- 會觸發(fā)
到此這篇關(guān)于MySQL 中 truncate、delete、drop的區(qū)別詳解的文章就介紹到這了,更多相關(guān)mysql truncate、delete、drop區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MySQL數(shù)據(jù)清除三劍客之DROP、DELETE與TRUNCATE深度對比指南
- MySQL刪除數(shù)據(jù)用法及區(qū)別詳解(DELETE、TRUNCATE?和?DROP)
- MySQL中DROP、DELETE與TRUNCATE的對比分析
- MySQL中DELETE、DROP和TRUNCATE的區(qū)別與底層原理分析
- 淺談MySQL中drop、truncate和delete的區(qū)別
- MySQL刪除表三種操作及delete、truncate、drop語句的區(qū)別
- MySQL刪除表數(shù)據(jù)、清空表命令詳解(truncate、drop、delete區(qū)別)
- MySQL中drop、truncate和delete的區(qū)別小結(jié)
- DELETE、TRUNCATE 和 DROP 在MySQL中的區(qū)別及功能使用示例
相關(guān)文章
MySQL數(shù)據(jù)庫遷移OpenGauss數(shù)據(jù)庫解析
這篇文章主要介紹了MySQL數(shù)據(jù)庫遷移OpenGauss數(shù)據(jù)庫解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
淺談sql語句中GROUP BY 和 HAVING的使用方法
GROUP BY語句和HAVING語句,經(jīng)過研究和練習,終于明白如何使用了,在此記錄一下同時添加了一個自己舉的小例子,通過寫這篇文章來加深下自己學習的效果,還能和大家分享下,同時也方便以后查閱,一舉多得,下面由小編來和大家一起學習2019-05-05
MYSQL數(shù)據(jù)庫連接池及常見參數(shù)調(diào)優(yōu)方式
這篇文章主要介紹了MYSQL數(shù)據(jù)庫連接池及常見參數(shù)調(diào)優(yōu)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

