TRUNCATE不能回滚,DELETE可以回滚:TRUNCATE是隐式提交的DDL操作,不写undo日志、不触发触发器、重置自增ID且不可回滚;DELETE是DML操作,支持事务回滚、触发器、WHERE条件及外键约束。

TRUNCATE 不能回滚,DELETE 可以
在 MySQL、PostgreSQL、Oracle 中,TRUNCATE TABLE 是隐式提交的 DDL 操作,执行后立即生效,ROLLBACK 无效。而 DELETE FROM 是 DML 操作,只要没 COMMIT,就能用 ROLLBACK 恢复数据。
常见错误现象:TRUNCATE TABLE logs 执行后发现删错了,再执行 ROLLBACK——数据已经没了。
- SQL Server 是个例外,允许在显式事务中回滚
TRUNCATE,但行为不稳定,不建议依赖 - 生产环境清空日志表前,如果不确定是否要保留最近几条,必须用
DELETE+WHERE - 权限受限账号可能有
DELETE权限但没有DROP或ALTER权限,导致TRUNCATE直接报错ERROR 1142 (42000): TRUNCATE command denied
TRUNCATE 不触发触发器,DELETE 会
如果你在表上定义了 BEFORE DELETE 或 AFTER DELETE 触发器(比如同步写审计日志、更新统计计数),TRUNCATE 完全绕过它们,静默执行;DELETE 则逐行调用,确保业务逻辑被激活。
使用场景:用户行为埋点表需记录每次删除动作来源,用 TRUNCATE 就会漏掉这条审计链路。
- 某些 ORM(如 Django ORM)默认禁用
TRUNCATE,就是因为它无法兼容信号(signals)机制 - 触发器里做了复杂校验或远程调用?
TRUNCATE会跳过这些开销,但代价是逻辑断层
TRUNCATE 重置自增 ID,DELETE 不重置
TRUNCATE 会让 AUTO_INCREMENT 计数器回归初始值(通常是 1);DELETE 保留当前最大 ID,下一条插入从原最大值 +1 开始。
性能影响明显:大表反复 DELETE 后,ID 可能飙到几百万,即使物理数据只剩几十行;TRUNCATE 后再插入,ID 从 1 起步,索引也回归紧凑结构。
- 测试环境重置数据时,用
TRUNCATE更干净 - 若业务依赖连续 ID(比如对外暴露的订单号),就不能用
TRUNCATE - PostgreSQL 中
TRUNCATE支持RESTART IDENTITY显式控制是否重置序列,MySQL 没这个选项,行为固定
TRUNCATE 不支持 WHERE,DELETE 支持
TRUNCATE TABLE orders WHERE status = 'cancelled' 语法错误,直接报 ERROR 1064 (42000);DELETE 必须配合 WHERE 才能条件删除。
TRUNCATE 不检查外键约束,遇到被其他表引用的父表会直接失败;DELETE 在满足级联或设为 NULL 的前提下仍可执行。
-
DELETE后表“体积”不变——高水位线(HWM)没降,后续全表扫描仍扫空洞;TRUNCATE真实释放空间,SHOW TABLE STATUS里的Data_length会大幅下降 -
TRUNCATE需要ALTER权限,DELETE只需要DELETE权限

















