You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:我的Azure SQL数据库表为何被永久锁定?

解决Azure SQL大规模UPDATE阻塞其他DML操作的实用方案

兄弟,你这情况我太熟了——当你在跑针对1M条记录的大规模UPDATE时,后续对同表的INSERT/UPDATE/DELETE操作被卡住,本质就是锁阻塞在搞鬼!SQL Server会给被更新的行(甚至可能因为锁升级变成表级锁)持有排他锁(X锁),其他操作请求锁的时候只能排队等大事务释放,自然就动不了了。

结合你的测试环境(单用户、隔离的数据库),给你几个落地的解决办法:

1. 把大UPDATE拆成批量小事务

别一次性更完所有记录,分批次处理,每批更个1000-5000条,每批提交一次事务。这样锁的持有时间会大幅缩短,其他操作就能插空执行了。

给你个现成的示例代码:

DECLARE @UpdatedRows INT = 1;
-- 循环直到没有可更新的记录
WHILE @UpdatedRows > 0
BEGIN
    BEGIN TRANSACTION;
    -- 每次更新1000条未处理的记录
    UPDATE TOP(1000) MyTable
    SET YourColumn = NewValue
    WHERE /* 这里放你的过滤条件,确保只更新没处理过的行 */;
    
    SET @UpdatedRows = @@ROWCOUNT; -- 获取本次更新的行数
    COMMIT TRANSACTION;
    -- 可选:加1秒延迟,给其他操作留足时间
    WAITFOR DELAY '00:00:01';
END

2. 开启快照隔离(测试环境放心用)

如果你只是做测试,不需要严格的强一致性,可以给数据库开READ_COMMITTED_SNAPSHOT ISOLATION,这样其他操作会读取行的版本,而不是傻等锁释放。

先检查当前数据库的快照隔离状态:

SELECT name, is_read_committed_snapshot_on 
FROM sys.databases WHERE name = '你的数据库名';

如果没开,直接执行开启命令(测试环境用ROLLBACK IMMEDIATE会强制终止现有事务,放心用):

ALTER DATABASE 你的数据库名 SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;

开启后,后续的INSERT/UPDATE/DELETE就不会被阻塞了,唯一要注意的是tempdb的开销会增加一点,但测试环境完全没问题。

3. 先排查阻塞情况(确认问题根源)

如果你想百分百确认是锁阻塞,在SSMS里跑这个查询,就能看到当前的阻塞链:

SELECT 
    blocking_session_id AS 阻塞会话ID,
    session_id AS 当前会话ID,
    resource_type AS 锁定资源类型,
    request_mode AS 请求锁类型,
    text AS 执行的SQL语句
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle)
WHERE blocking_session_id <> 0;

跑出来的结果会明确告诉你,是不是你的大规模UPDATE会话在阻塞其他操作,以及被卡住的查询是什么。

4. 优化UPDATE的执行计划,加快执行速度

如果你的UPDATE跑得慢,锁持有时间自然就长。可以看看执行计划有没有全表扫描——如果WHERE条件里的列没加索引,SQL Server会扫整个表,锁的范围大还慢。给过滤条件的列加个非聚集索引,能大幅加快UPDATE速度,减少锁的持有时间。


内容的提问来源于stack exchange,提问作者kspearrin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 06:56:32