truncate 不记录行级日志,因其是 ddl 操作,不生成 undo log,仅写少量元数据日志(如 binlog 中的 ddl 事件),不触发触发器,不可回滚,且重置 auto_increment。

Truncate 会记录日志吗?
不会,TRUNCATE TABLE 是 DDL 操作,在大多数存储引擎(如 InnoDB 和 MyISAM)中不写入 undo 日志或 redo 日志的行级变更记录,也不触发 DELETE 触发器。它本质是“删掉表、重建空表”,所以速度极快,且事务中无法回滚(执行即提交)。
但注意:TRUNCATE 仍会写少量元数据日志(如 binlog),用于主从复制;如果开启了 binlog_format=ROW,MySQL 5.7+ 会以 DDL 事件形式记录整个操作,而非逐行日志——这不算“行级日志”,但复制链路上仍可追踪。
Truncate 和 Delete 的关键区别在哪?
别拿 TRUNCATE 当 DELETE FROM table 用,它们不是同一路数:
-
TRUNCATE重置AUTO_INCREMENT计数器;DELETE不重置(除非显式ALTER TABLE ... AUTO_INCREMENT = 1) -
TRUNCATE要求对表有DROP权限(因为内部会先DROP再CREATE);DELETE只需DELETE权限 -
TRUNCATE不能带WHERE;DELETE可以条件删除 -
TRUNCATE在外键约束下会失败(除非禁用FOREIGN_KEY_CHECKS);DELETE受外键级联规则控制
执行 Truncate 前必须检查的三件事
直接跑 TRUNCATE TABLE users; 很快,但出错后恢复成本高:
- 确认表没被其他会话加锁(尤其是长时间未提交的事务持有
MDL锁),否则TRUNCATE会阻塞 - 检查是否有外键引用该表:查
information_schema.KEY_COLUMN_USAGE或用SHOW CREATE TABLE看CONSTRAINT定义 - 确认 binlog 开启状态和格式:
SELECT @@sql_log_bin, @@binlog_format;—— 如果关了 binlog,主从会丢数据;如果开了但下游没同步好,可能造成不一致
替代方案:什么时候不该用 Truncate?
想清空但保留自增 ID、或只清部分分区、或要审计每行删除动作,就别碰 TRUNCATE:
- 需要保留
AUTO_INCREMENT值?用DELETE FROM table+ALTER TABLE table AUTO_INCREMENT = N(N 是原值) - 大表但只想清旧数据?考虑按时间分区后
DROP PARTITION,比TRUNCATE更精准 - 要求每行删除都进 audit log 或触发器生效?只能用
DELETE,哪怕慢也得忍
真正“快速清空且不记行日志”的场景其实很窄:开发库重置、ETL 临时表复位、测试数据刷盘——生产环境动 TRUNCATE 前,最好先 mysqldump --no-data 备份表结构,再执行。











