TRUNCATE无法回滚是铁律,因其属DDL操作且隐式提交;DELETE可回滚但性能差、开销大;TRUNCATE快如闪电但受外键、触发器、自增ID等限制。

TRUNCATE 无法回滚是铁律,别信“加了 BEGIN 就能撤”
在 MySQL 和 Oracle 中,TRUNCATE TABLE 是 DDL 操作,执行即隐式提交——哪怕你手动写了 BEGIN TRANSACTION,它也会立刻生效,ROLLBACK 完全无效。实测中,以下操作后数据永远丢失:
START TRANSACTION;而
TRUNCATE TABLE logs;
ROLLBACK;
DELETE FROM logs 在同一事务里可以随时 ROLLBACK 恢复。唯一例外是 SQL Server(支持 DDL 回滚),但跨数据库迁移时绝不能依赖这点。
删 100 万行,DELETE 耗时 82 秒,TRUNCATE 只要 0.01 秒
性能差距不是线性,而是数量级碾压:
-
DELETE逐行标记、写 undo/redo 日志、触发器校验、行锁排队——100 万行产生约 200MB 日志,CPU 占用峰值超 70% -
TRUNCATE直接释放数据页,只记一条元数据变更,日志几乎为零,全程表级锁但毫秒级完成 - 中等规模(10 万行)已见分晓:
DELETE平均 8.2 秒 vsTRUNCATE0.01 秒
DELETE 不仅慢,还可能拖垮主库 I/O 和连接池。外键、触发器、自增 ID —— 这些地方一踩就报错
看似只是“删数据”,但底层行为差异极大:
- 有子表外键引用?
TRUNCATE直接报错;DELETE可配ON DELETE CASCADE或先禁用约束 - 表上有
AFTER DELETE触发器?TRUNCATE完全不触发,业务逻辑会断掉 -
auto_increment值:DELETE 后下一条插入仍是原最大值+1;TRUNCATE 后重置为 1(MySQL 默认) - 权限要求也不同:
TRUNCATE需要DROP权限,不是只有DELETE权限就够
SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME = 'your_table'。该用哪个?看这三点就足够判断
不用背区别,直接按场景选:
- 要删全部数据 + 不需要回滚 + 没外键 + 不依赖触发器 → 无条件选
TRUNCATE - 要删部分数据(比如
WHERE created_at )→ 只能用DELETE - 要删全部但担心误操作 → 先
CREATE TABLE backup AS SELECT * FROM t,再TRUNCATE,别指望 rollback
DELETE FROM t 不释放磁盘空间,后续必须 OPTIMIZE TABLE t 才能回收——而 TRUNCATE 一步到位。











