最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
为何MySQL执行DELETE语句比TRUNCATE更容易产生锁等待?
时间:2026-07-16 08:21:52 编辑:袖梨 来源:一聚教程网
DELETE长时间持锁,因其作为DML需逐行加X锁、写undo log、维护MVCC链,全表扫描时锁持续至事务结束;TRUNCATE为DDL,仅瞬时获取SCH_M表级锁并隐式提交,不参与事务锁队列,故几乎无锁等待。
因为DELETE是DML,全程走行级锁+事务机制;TRUNCATE是DDL,只瞬时持表级锁且隐式提交。
DELETE为什么会长时间持有锁
DELETE不是“删完就放锁”,而是边删边锁、边写日志、边维护MVCC版本链:
-
DELETE FROM t会启动一个事务,对每一行加X锁(或间隙锁),直到事务结束才释放 - 没WHERE条件时,InnoDB仍要全表扫描聚簇索引,逐行加锁、打删除标记、写
undo log - 若表无合适索引,可能升级为表锁;高并发下容易出现
LOCK_WAIT或死锁 - 在
SHOW ENGINE INNODB STATUS里常看到大量RECORD LOCKS和长时间Trx has been waiting
TRUNCATE锁等待几乎为零的底层原因
TRUNCATE根本不参与事务锁队列,它压根不“等”锁,只做两件事:抢锁、失败或秒过:
- 它申请的是
SCH_M(schema modification)锁,粒度是表级,但持有时间以毫秒计 - 一旦发现表被
LOCK TABLES t READ或外键引用,立刻报错退出:ERROR 1099或ERROR 1701,绝不排队等待 - 执行即隐式提交,不进事务上下文,所以
SELECT FOR UPDATE或其他DML不会因它进入锁等待队列 - 主从复制中,从库收到的是轻量DDL事件,不会像
DELETE那样堆积上万条row event导致应用线程卡住
线上误用TRUNCATE反而引发更隐蔽的问题
看似“不卡锁”很安全,但实际容易踩进事务截断和数据一致性陷阱:
- 在长事务里执行
TRUNCATE TABLE t,MySQL会自动COMMIT当前事务——你后面跟的ROLLBACK完全无效,下游可能读到中间态 - TRUNCATE重置
AUTO_INCREMENT,如果业务依赖ID单调递增(比如对外暴露的订单号),首次插入可能撞上旧ID - 它不触发
ON DELETE触发器,也不检查外键约束(除非被引用),这些“省略”在某些场景下就是逻辑漏洞
真正决定是否用TRUNCATE的,从来不是“快不快”,而是“能不能接受不可回滚、自增重置、触发器失效、外键拒绝”这四点。锁只是表象,语义差异才是根本。
相关文章
- 王者荣耀世界零氪玩家如何生存 07-28
- 快手极速版怎么绑定手机号 07-28
- 明日方舟和轻松小熊联动活动内容一览 07-28
- 逆战未来黎明之光 逆战未来黎明之光玩法机制与新手入门指南 07-28
- 植物大战僵尸融合版毁灭土豆地雷介绍 07-28
- 逆战未来飓风之龙 逆战未来飓风之龙武器获取方法详解 07-28