
TRUNCATE执行后无法回滚,且不记逐行binlog
TRUNCATE是DDL操作,一执行就隐式提交,ROLLBACK完全无效。你在事务里写BEGIN; TRUNCATE TABLE t; ROLLBACK;,表照样空了。binlog里只有一条TRUNCATE TABLE t语句(SBR模式下),没有每行删除记录——这意味着:主从切换后若想按时间点闪回某几条误删数据,根本做不到;而DELETE FROM t每删一行都记row event,理论上可解析binlog做条件恢复。
外键引用直接导致TRUNCATE失败,DELETE却能走级联逻辑
当表被其他表通过FOREIGN KEY引用时,TRUNCATE TABLE t会立刻报错:ERROR 1701 (HY000): Cannot truncate a table referenced in a foreign key constraint。你不能靠SET FOREIGN_KEY_CHECKS = 0绕过再恢复,因为这会破坏参照完整性,尤其在复制环境里极易引发主从不一致。而DELETE FROM t会正常触发ON DELETE CASCADE或ON DELETE SET NULL,行为可预测、可审计。
自增ID重置不是便利,而是业务隐患
TRUNCATE强制把AUTO_INCREMENT值归1,DELETE则保留原最大值。表面看TRUNCATE“干净”,但很多场景下这是危险的:下游系统依赖ID连续性做分页或幂等校验;ID溢出风险本已逼近(比如INT UNSIGNED快到42亿),重置后反而加速撞墙;缓存键含ID时,旧缓存未清完就插入ID=1的新记录,可能覆盖错误数据。真要重置,应显式用ALTER TABLE t AUTO_INCREMENT = N,而非依赖TRUNCATE副作用。
大表上TRUNCATE看似快,但物理空间未必立刻释放
对innodb_file_per_table = OFF的实例,TRUNCATE只是把数据页归还给共享表空间(ibdata1),OS层面看不到磁盘空间回收;此时SHOW TABLE STATUS显示Data_length为0,但du -sh /var/lib/mysql/ibdata1大小不变。真正释放需停库+dump/reload,或改配置后重建。而DELETE虽慢,配合OPTIMIZE TABLE(低峰期)至少能整理碎片、收缩.ibd文件——这点常被忽略,直到磁盘告警才反应过来。











