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

Azure SQL DB 并发事务处理及行级锁识别实现问题咨询

问题解答

第2点:实现其他会话可更新非锁定行的方案

你遇到的其他行无法更新的问题,不是表上的IX意向锁导致的,IX锁只会阻塞对整个表的共享/排他锁,不会阻塞其他行的更新操作。根因是你加UPDLOCK的SELECT语句触发了全表/全索引扫描,扫描过程中会给所有途经的行加U锁,即便加了ROWLOCK提示也无效。
解决步骤如下:

  • 确保表有主键(默认创建聚集索引),加UPDLOCK的SELECT语句必须用主键等值作为WHERE条件,或者用到唯一非聚集索引的等值匹配,保证执行计划是**索引查找(Seek)**而非扫描。此时只会给目标行加U锁,完全不影响其他行的更新。
    示例加锁语句:
    BEGIN TRANSACTION;
    -- 必须保证WHERE后的主键匹配能走到索引查找
    SELECT * FROM 你的表名 WITH (UPDLOCK, ROWLOCK) WHERE 主键列 = 目标主键值;
    -- 此处写后续的更新业务逻辑
    COMMIT TRANSACTION;
    
  • 不需要加READPAST提示,该提示会让查询跳过已加锁的行,可能导致你无法获取到目标行的锁。
  • 如果确认执行计划是索引查找仍出现锁阻塞,可手动关闭目标表的锁升级:ALTER TABLE 你的表名 SET (LOCK_ESCALATION = DISABLE);,Azure SQL DB基本层数据量普遍不大,锁升级概率很低,该操作仅作为兜底方案。

第3点:行级锁与主键、锁定用户的匹配方案

该需求可以实现,借助SQL Server内置的%%lockres%%虚拟列即可关联行锁资源和实际行数据,具体查询逻辑如下:

-- 提前替换SQL中的占位符:你的表名、主键列名
SELECT 
    s.session_id AS 会话ID,
    s.login_name AS 锁定用户账号,
    t.resource_description AS 行锁资源标识,
    d.主键列名 AS 被锁行主键值
FROM sys.dm_tran_locks t
INNER JOIN sys.dm_exec_sessions s 
    ON t.request_session_id = s.session_id
INNER JOIN sys.objects o 
    ON t.resource_associated_entity_id = o.object_id
CROSS APPLY (
    SELECT 主键列名 
    FROM 你的表名 
    WHERE %%lockres%% = t.resource_description
) d
WHERE 
    o.name = '你的表名'
    -- 堆表用resource_type = 'RID',聚集索引表用resource_type = 'KEY'
    AND t.resource_type = 'KEY' 
    AND t.request_mode IN ('U', 'X')
    AND t.request_status = 'GRANT';

注意事项:

  • 大表查询时可先过滤出目标表的行锁资源列表,再单独查询每行的主键值,避免全表扫描产生性能开销。

第1点确认

你当前用UPDLOCK实现其他用户可读的方案是正确的,因为RCSI(读提交快照隔离)级别下,读操作不会请求共享锁,直接读取行版本数据,完全不会被U/X锁阻塞,符合你的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 10:54:02