Sql-Server
UPLOCK 避免多次讀取
給定以下表結構…
Orders ====== OrderId int PK OrderEvent =========== OrderEventId int PK OrderId int FK EventTypeId int FK
我有多個並發程序選擇訂單,但每個訂單總體上只能讀取一次。因此,在檢索到訂單後,我需要在 OrderEvent 表中添加一行以標記已讀取訂單(EventTypeId = 1)。
所以我的想法是對閱讀進行以下查詢…
SELECT * FROM Orders o WITH (UPDLOCK) WHERE NOT EXISTS (SELECT * FROM OrderEvent oe WHERE oe.OrderId = o.OrderID AND EventTypeId = 1)
這在事務中執行,並在讀取後添加訂單事件行以將訂單標記為已讀取。
那麼問題來了,這樣能保證每個訂單只能檢索一次嗎?
我不確定的是何時將鎖放在訂單行上?是在評估 where 子句之前還是之後?
UPDLOCK 將阻止後續呼叫讀取已提取的訂單,但不允許後續呼叫讀取其他呼叫,因為它將等待讀取符合條件的所有行,並且您已明確告訴引擎您打算在此事務中更新它們。
如果您還添加了一個 READPAST 提示,它將允許後續呼叫獲取之前未提取的任何可用行。
SELECT * FROM Orders o WITH (UPDLOCK,READPAST) WHERE NOT EXISTS (SELECT * FROM OrderEvent oe WHERE oe.OrderId = o.OrderID AND EventTypeId = 1)