3 回答
TA贡献1802条经验 获得超4个赞
在测试行是否存在时传递updlock,rowlock,holdlock提示。Holdlock确保所有插件都已序列化;行锁允许并发更新现有行。
如果您的PK是bigint,则更新可能仍会阻止,因为内部哈希会退化为64位值。
begin tran -- default read committed isolation level is fine
if not exists (select * from <table> with (updlock, rowlock, holdlock) where <PK = ...>
-- insert
else
-- update
commit
TA贡献1946条经验 获得超3个赞
编辑:Remus是正确的,条件插入w / where子句不能保证相关子查询和表插入之间的状态一致。
正确的表提示可能会强制保持一致状态。INSERT <table> WITH (TABLOCKX, HOLDLOCK)似乎有效,但是我不知道这是否是有条件插入的最佳锁定级别。
在像Remus所述的琐碎测试中,TABLOCKX, HOLDLOCK显示的插入量是没有表提示的插入量的5倍,并且没有PK错误或过程。
原始答案,不正确:
这是原子的吗?
是的,条件插入w / where子句是原子的,您的INSERT ... WHERE NOT EXISTS() ... UPDATE表单是执行UPSERT的正确方法。
我将IF @@ROWCOUNT = 0在INSERT和UPDATE之间添加:
INSERT INTO <table>
SELECT <natural keys>, <other stuff...>
WHERE NOT EXISTS
-- no race condition here
( SELECT 1 FROM <table> WHERE <natural keys> )
IF @@ROWCOUNT = 0 BEGIN
UPDATE ...
WHERE <natural keys>
END
单个语句始终在事务中执行,无论是它们自己(自动提交和隐式),还是与其他语句(显式)一起执行。
- 3 回答
- 0 关注
- 598 浏览
添加回答
举报