DELETE长时间持锁,因其作为DML需逐行加X锁、写undo log、维护MVCC链,全表扫描时锁持续至事务结束;TRUNCATE为DDL,仅瞬时获取SCH_M表级锁并隐式提交,不参与事务锁队列,故几乎无锁等待。
因为DELETE是DML,全程走行级锁+事务机制;TRUNCATE是DDL,只瞬时持表级锁且隐式提交。
DELETE不是“删完就放锁”,而是边删边锁、边写日志、边维护MVCC版本链:
DELETE FROM t 会启动一个事务,对每一行加X锁(或间隙锁),直到事务结束才释放undo log
LOCK_WAIT或死锁SHOW ENGINE INNODB STATUS里常看到大量RECORD LOCKS和长时间Trx has been waiting
TRUNCATE根本不参与事务锁队列,它压根不“等”锁,只做两件事:抢锁、失败或秒过:
SCH_M(schema modification)锁,粒度是表级,但持有时间以毫秒计LOCK TABLES t READ或外键引用,立刻报错退出:ERROR 1099 或 ERROR 1701,绝不排队等待SELECT FOR UPDATE或其他DML不会因它进入锁等待队列DELETE那样堆积上万条row event导致应用线程卡住看似“不卡锁”很安全,但实际容易踩进事务截断和数据一致性陷阱:
TRUNCATE TABLE t,MySQL会自动COMMIT当前事务——你后面跟的ROLLBACK完全无效,下游可能读到中间态AUTO_INCREMENT,如果业务依赖ID单调递增(比如对外暴露的订单号),首次插入可能撞上旧IDON DELETE触发器,也不检查外键约束(除非被引用),这些“省略”在某些场景下就是逻辑漏洞真正决定是否用TRUNCATE的,从来不是“快不快”,而是“能不能接受不可回滚、自增重置、触发器失效、外键拒绝”这四点。锁只是表象,语义差异才是根本。