Sql-Server

如何將 UpdateLock 放置在具有索引的行上

  • June 21, 2016

假設我在 SQL Server 2014 上有這樣的表:

CREATE TABLE Accounts (
   Id int IDENTITY(1,1) NOT NULL,
   OwnerId int NOT NULL,
   Balance bigint NOT NULL
CONSTRAINT PK_Account PRIMARY KEY CLUSTERED (Id ASC),
CONSTRAINT UQ_OwnerId UNIQUE NONCLUSTERED (OwnerId)
)

讓我們假設有一行Id=1,OwnerId=1Balance=100

我需要為特定帳戶選擇 Id (僅Id),但同時希望鎖定該行以防止更新。

在第一個會話中,我執行以下語句(在事務中):

SELECT Id FROM Accounts WITH (UPDLOCK, ROWLOCK) WHERE OwnerId = 1;

在第二個會話中,我執行以下語句(在另一個事務中):

UPDATE Accounts SET Balance = 500 WHERE Id = 1;

兩個語句都在沒有被阻塞的情況下完成,因為第一個語句鎖定在唯一索引上。我該怎麼做才能強制第二條語句等待?

我已經提出了解決方案,但不喜歡:

  1. 在第一個查詢中選擇整行 ( SELECT *) 而不是僅選擇 id → 這會導致我的應用程序成本過多。
  2. 向第一個查詢添加INDEX=PK_Account提示以強制鎖定 PK → 我會失去性能,因為這會導致聚集索引掃描。

有沒有其他方法可以僅檢索Id(使用UQ_OwnerId 時)並防止對該行進行任何更新?

兩次尋找,鎖定PK,

select id 
from Accounts WITH (UPDLOCK) 
where id = (select a.id from Accounts a where a.OwnerId=1)

引用自:https://dba.stackexchange.com/questions/141385