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

Microsoft SQL Server中UPDLOCK能否阻止IF EXISTS查询对应键的插入?

关于SQL Server中UPDLOCK阻止并发插入的问题解答

首先直接给你结论:是的,把UPDLOCK和HOLDLOCK一起用,完全能阻止针对同一AccountName的并发插入操作,下面给你拆解背后的逻辑:

先搞懂两个锁的作用

1. 单独用UPDLOCK的局限

UPDLOCK会给查询命中的行加更新锁,这种锁和共享锁兼容,但和其他更新锁、排他锁互斥。不过这里有个关键问题:如果你的查询没找到匹配的行(也就是第一次执行时SuperCustomer还不存在),UPDLOCK没办法锁定“这个不存在的键对应的范围”,这时候多个并发请求可能同时通过IF NOT EXISTS的判断,一起进入插入步骤,最后触发唯一约束的冲突错误。

2. HOLDLOCK是关键补全

HOLDLOCK其实就是把事务隔离级别设为SERIALIZABLE,它会让查询启用键范围锁——不仅锁定已存在的行,还会锁定AccountName = 'SuperCustomer'这个值对应的键范围,相当于在这个位置“占个坑”,其他事务根本没法在这个范围内插入新行。

当第一个事务执行SELECT ... WITH (UPDLOCK, HOLDLOCK)且没找到匹配行时,会在SuperCustomer对应的键范围上锁死,其他并发的相同查询会被阻塞,直到第一个事务完成插入(或者回滚),这样就彻底避免了多个事务同时插入重复数据的情况。

给你提个小修正

你的代码里表名有点不一致:建表用的是[Customer],但查询里写的是[Customers],得改成统一的。另外建议显式加事务,确保锁的生命周期覆盖整个操作,修正后的代码如下:

BEGIN TRANSACTION;
IF NOT EXISTS(SELECT [AccountName] FROM [Customer] WITH (UPDLOCK, HOLDLOCK) WHERE [AccountName] = 'SuperCustomer') 
BEGIN 
    INSERT INTO [Customer] ([AccountName]) VALUES ('SuperCustomer') 
END
COMMIT TRANSACTION;

总结一下

单独的UPDLOCK搞不定“不存在键的并发插入”,但**UPDLOCK + HOLDLOCK的组合**通过键范围锁把目标键的位置彻底锁住,完美保证你这个“不存在则插入”的逻辑在高并发场景下不会出问题,不会触发唯一约束的报错。

内容的提问来源于stack exchange,提问作者Michael J. Gray

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:12:36