Sql-Server
如何將 UpdateLock 放置在具有索引的行上
假設我在 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=1
和Balance=100
。我需要為特定帳戶選擇 Id (僅Id),但同時希望鎖定該行以防止更新。
在第一個會話中,我執行以下語句(在事務中):
SELECT Id FROM Accounts WITH (UPDLOCK, ROWLOCK) WHERE OwnerId = 1;
在第二個會話中,我執行以下語句(在另一個事務中):
UPDATE Accounts SET Balance = 500 WHERE Id = 1;
兩個語句都在沒有被阻塞的情況下完成,因為第一個語句鎖定在唯一索引上。我該怎麼做才能強制第二條語句等待?
我已經提出了解決方案,但不喜歡:
- 在第一個查詢中選擇整行 (
SELECT *
) 而不是僅選擇 id → 這會導致我的應用程序成本過多。- 向第一個查詢添加
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)