truncate完全不走innodb行级日志路径,因其是ddl操作,直接释放原表segment并新建空segment,跳过聚簇索引扫描、行锁、undo log和逐行binlog,仅记元数据变更。

TRUNCATE 为什么完全不走 InnoDB 行级日志路径
因为 TRUNCATE TABLE 在 InnoDB 中根本不是 DML 操作,它不调用 row_delete_for_mysql(),而是直接进入 DDL 流程,执行「释放原表 segment + 新建空 segment」。这意味着:
- 不扫描聚簇索引 B+ 树,不访问任何数据页
- 不为每一行加 X 锁,也不触发锁升级逻辑
- 完全跳过 undo log 写入 —— 所以不可回滚
- redo log 只记页释放和元数据变更(如 FSEG_HEADER 重置),不是逐行变更记录
- binlog 只写一条
TRUNCATE TABLE tDDL 事件,而非上万条 row event
你看到的“秒删千万行”,其实是文件系统层面的 ftruncate() 或段回收动作,跟数据内容无关。
DELETE FROM t 卡住的典型表现和底层原因
哪怕没写 WHERE,DELETE FROM t 仍是标准 DML:InnoDB 启动事务、遍历聚簇索引、逐行标记 delete bit、生成 undo log、刷 binlog、等 purge 线程异步清理。常见卡顿现象包括:
-
SHOW PROCESSLIST显示状态为Updating或Writing to net - 主从延迟突增(尤其
binlog_format = ROW时) - 事务长时间持有锁,阻塞其他 DML
-
innodb_log_file_size频繁刷盘,甚至触发innodb_force_recovery -
undo tablespace暴涨,占用大量磁盘空间
这不是“慢”,是整套 MVCC + 日志 + 锁机制被压满的表现。
TRUNCATE 能否真正释放磁盘空间,取决于这个配置
关键看 innodb_file_per_table 是否为 ON:
- 为
ON(默认):TRUNCATE 后.ibd文件大小立即回落,ls -lh table_name.ibd可见变化 - 为
OFF:数据仍在共享表空间ibdata1中,TRUNCATE 不释放操作系统可见空间
验证是否生效,别只看文件大小,执行:
SELECT DATA_LENGTH, INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t';
若数值未大幅下降,先查 SHOW VARIABLES LIKE 'innodb_file_per_table';。为 OFF 时,只能导出 + DROP + 重建 + 导入才能回收。
容易被忽略的隐式行为与权限陷阱
TRUNCATE 表面简单,但几个关键点常被跳过检查:
- 它需要
DROP权限(不是DELETE权限),在严格权限模型下可能报ERROR 1142 (42000): TRUNCATE command denied - 在事务中执行会隐式提交,导致当前事务提前结束 ——
TRUNCATE后再ROLLBACK无效 - 不触发
BEFORE/AFTER DELETE触发器,如果业务依赖触发器写审计日志或发消息,就直接跳过 - 外键约束检查被绕过,但前提是“无其他表用
FOREIGN KEY ... ON DELETE CASCADE/RESTRICT引用该表”,否则报错Cannot truncate a table referenced in a foreign key constraint
真正麻烦的不是“快不快”,而是它快得让人忘了它改的是元数据,不是数据 —— 一旦误用,连 undo 的机会都没有。










