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 關注
- 627 瀏覽
添加回答
舉報