DELETE阻塞主因是锁升级而非锁本身:当行锁超5000个(如无索引导致全表扫描),SQL Server自动升为表级排他锁以节省内存,此时需检查sys.dm_tran_locks中TAB X锁及执行计划是否存在Scan。

SQL Server 执行 DELETE 产生大量阻塞,大概率不是锁本身的问题,而是锁升级(Lock Escalation)被意外触发,且底层缺乏有效索引支撑。
为什么 DELETE 会突然升级成表锁?
SQL Server 默认对 DELETE 使用行锁,但一旦单个事务持有的行锁数量超过约 5000 个,引擎就会自动发起锁升级——把所有行锁合并为一个表级排他锁(TAB X)。这不是 bug,是内存保护机制:每个锁占约 96 字节,5000 行锁 ≈ 480KB,20 万行就是近 20MB 锁内存开销。
触发锁升级的常见条件包括:
-
WHERE条件列上没有索引,导致全表扫描,扫描过程中每行都加锁 - 事务未显式控制大小,一次删几十万行
- 隔离级别设为
REPEATABLE READ或SERIALIZABLE,延长锁持有时间 - 表上有多个非聚集索引,
DELETE需同步更新所有索引键,锁数量翻倍
如何确认当前阻塞是否由锁升级引起?
运行以下查询,检查是否有大量 TAB 级别的 X(排他)锁正在阻塞其他会话:
SELECT request_session_id, resource_type, resource_description,
request_mode, request_status, OBJECT_NAME(p.object_id) AS object_name
FROM sys.dm_tran_locks l
JOIN sys.partitions p ON l.resource_associated_entity_id = p.hobt_id
WHERE resource_database_id = DB_ID()
AND resource_type = 'OBJECT'
AND request_mode = 'X'
AND request_status = 'WAIT'
如果返回结果中 object_name 是你正在删除的目标表,且 request_session_id 对应的是那个 DELETE 语句的 SPID,基本可断定是锁升级导致的阻塞。
补充验证方式:
- 查
sys.dm_exec_requests中该 SPID 的wait_type是否为LCK_M_X - 用
DBCC TRACEON(1204, -1)捕获死锁图(若已发生死锁) - 观察执行计划中是否出现“Clustered Index Scan”或“Table Scan”
索引缺失如何放大锁问题?
没有索引时,DELETE FROM Orders WHERE OrderDate 不是“找出行再删”,而是“逐行比对再删”——每一行都要读、都要加锁、都要判断是否满足条件。哪怕最终只删 100 行,也可能在扫描过程中锁住 10 万行。
有索引也不一定够用,要注意:
- 索引必须覆盖
WHERE条件列(如OrderDate),否则仍走扫描 - 复合索引顺序很重要:
CREATE INDEX IX_OrderDate_Status ON Orders(OrderDate, Status)对WHERE OrderDate 有效;但对纯OrderDate查询,效果取决于统计信息和优化器选择 - 若表有 5 个非聚集索引,
DELETE实际要维护 6 个结构(含聚集索引),锁申请量远超行数本身
怎么改写才能避开锁升级?
核心思路是:不让单个事务跨过 5000 行锁阈值。不依赖 SET ROWCOUNT(已弃用),改用 TOP (n) + 循环或 CTE 分批:
WHILE 1=1
BEGIN
DELETE TOP (5000) FROM Orders
WHERE OrderDate IF @@ROWCOUNT = 0 BREAK;
WAITFOR DELAY '00:00:00.01'; -- 减轻日志压力与锁竞争
END
关键细节:
- 每次只删
TOP (5000),确保事务内锁数可控 - 避免在循环中重复计算
WHERE条件,尤其是涉及函数(如DATEADD)时,可能阻止索引使用 - 如果表极大且长期存在归档需求,优先考虑分区切换(
SWITCH PARTITION),这是零锁操作 - 切忌在 OLTP 主库上跑无
TOP的大DELETE,哪怕加了索引——锁升级阈值可调,但调高只是掩盖问题
真正容易被忽略的点是:锁升级本身不可怕,可怕的是它暴露了索引设计盲区和事务粒度失控。一次删 200 万行,不管怎么分批,背后都该问一句:这个数据是不是早该按月/按年分区?这个 WHERE 条件是不是业务上本就该走索引覆盖?










