亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

SQL Server 2005中的原子UPSERT

SQL Server 2005中的原子UPSERT

12345678_0001 2019-11-29 10:27:09
在SQL Server 2005中執行原子“ UPSERT”(存在時為UPDATE,否則為INSERT)的正確模式是什么?我在SO上看到了很多代碼(例如,請參閱檢查是否存在一行,否則請插入),其代碼分為以下兩部分:UPDATE ...FROM ...WHERE <condition>-- race condition risk hereIF @@ROWCOUNT = 0  INSERT ...要么IF (SELECT COUNT(*) FROM ... WHERE <condition>) = 0  -- race condition risk here  INSERT ...ELSE  UPDATE ...其中<condition>是自然鍵的評估。上述方法似乎都不能很好地處理并發。如果我不能讓兩行具有相同的自然鍵,則上述所有情況似乎都有在競爭條件場景中插入具有相同自然鍵的行的風險。我一直在使用以下方法,但是我很驚訝沒有在人們的回應中看到它,因此我很奇怪它出了什么問題:INSERT INTO <table>SELECT <natural keys>, <other stuff...>FROM <table>WHERE NOT EXISTS   -- race condition risk here?   ( SELECT 1 FROM <table> WHERE <natural keys> )UPDATE ...WHERE <natural keys>請注意,此處提到的競爭條件與先前代碼中的競爭條件不同。在早期的代碼中,問題在于幻像讀取(行在其他會話之間插入到UPDATE / IF之間或SELECT / INSERT之間)。在上面的代碼中,競爭條件與DELETE有關。在(WHERE NOT EXISTS)執行之后但在INSERT執行之前,是否可以將另一個行刪除匹配的行?目前尚不清楚WHERE NOT EXISTS在何處與UPDATE一起鎖定任何內容。這是原子的嗎?我在SQL Server文檔中找不到該文檔的記錄位置。編輯: 我意識到這可以使用事務來完成,但是我想我需要將事務級別設置為SERIALIZABLE以避免幻像讀取問題?對于這樣一個普遍的問題,這肯定是大材小用嗎?
查看完整描述

3 回答

?
慕虎7371278

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


查看完整回答
反對 回復 2019-11-29
?
智慧大石

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

單個語句始終在事務中執行,無論是它們自己(自動提交和隱式),還是與其他語句(顯式)一起執行。


查看完整回答
反對 回復 2019-11-29
  • 3 回答
  • 0 關注
  • 627 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號