简体   繁体   English

如何在存储过程中提交事务之前在SQL Server中锁定选择的行

[英]How to lock a SELECted rows in Sql Server until transaction is COMMITTED in a Stored Procedure

I would like to lock some rows in a table with a SELECT statement in SP. 我想用SP中的SELECT语句锁定表中的某些行。 I have transaction in my SP. 我的SP中有交易。 I would like to lock all rows that I SELECT after BEGIN TRANSACTION.So, I would like to release those rows after COMMIT/ROLLBACK. 我想锁定在BEGIN TRANSACTION之后选择的所有行。因此,我想在COMMIT / ROLLBACK之后释放这些行。

I have tried XLOCK,UPDLOCK,HOLDLOCK but none of them does what I expect. 我已经尝试过XLOCK,UPDLOCK,HOLDLOCK,但是它们都没有达到我的期望。

Here is my sample code... 这是我的示例代码...

BEGIN TRANSACTION 
    -- I WANT TO LOCK EMPLOYEES LIVE IN ISTANBULL
    SELECT ID FROM EMPLOYEES WITH(XLOCK) WHERE CITY='ISTANBUL'
    ....
    ....
    ....
COMMIT
-- LOCKED ROWS SHOULD BE RELEASED AFTER COMMIT.

any suggestion? 有什么建议吗?

Your code should work fine. 您的代码应该可以正常工作。

Suppose, you are selecting rows with UPDLOCK/XLOCK. 假设您正在使用UPDLOCK / XLOCK选择行。

First Transaction 首次交易

BEGIN TRAN
SELECT ID FROM EMPLOYEES WITH(UPDLOCK, XLOCK) WHERE CITY='ISTANBUL'
--COMMIT TRAN (Stopping commit to keep the lock running)

Now try run following in another window. 现在尝试在另一个窗口中运行以下命令。

Second Transaction 第二次交易

BEGIN TRAN
SELECT ID FROM EMPLOYEES WITH(UPDLOCK, XLOCK) WHERE CITY='ISTANBUL'
COMMIT TRAN

Your second transaction will not be able to select until you commit your first transaction. 在提交第一笔交易之前,您将无法选择第二笔交易。 Because multiple UPDLOCK or XLOCK can't be applied together on a resource. 因为不能将多个UPDLOCK或XLOCK一起应用于资源。

Now, if you read rows without locking with uncommitted first transaction then second transaction will not be prevented by the first. 现在,如果您未锁定未提交的第一个事务而读取行,则第一个事务将不会阻止第二个事务。

Second Transaction 第二次交易

BEGIN TRAN
SELECT ID FROM EMPLOYEES WHERE CITY='ISTANBUL'
COMMIT TRAN

Because in second transaction no lock applied so it will not be prevented by first transactions UPDLOCK or XLOCK. 因为在第二个事务中没有应用锁定,所以第一个事务UPDLOCK或XLOCK不会阻止它。

Now to prevent any read with another read you need to change your ISOLATION LEVEL TO SERIALIZABLE. 现在,为了防止再读任何书,您需要将ISOLATION LEVEL更改为SERIALIZABLE。

First Transaction 首次交易

BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE  
SELECT ID FROM EMPLOYEES WHERE CITY='ISTANBUL'
--COMMIT TRAN (Stopping commit to keep the lock running)

Second Transaction 第二次交易

BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 
SELECT ID FROM EMPLOYEES WHERE CITY='ISTANBUL'
COMMIT TRAN

Now second transaction will be blocked by first transaction. 现在,第二笔交易将被第一笔交易阻止。 Though no lock applied during read but in transaction isolation level SERIALIZABLE a read transaction will block read of another transaction over same resource. 尽管在读取过程中未应用锁定,但在事务隔离级别SERIALIZABLE中,读取事务将阻止通过同一资源读取另一个事务。

Now If you select with NOLOCK then there is no transaction lock or isolation level exists to block you. 现在,如果使用NOLOCK选择,则不存在任何事务锁定或隔离级别可以阻止您。

Hope these helps :) 希望这些帮助:)

FROM TABLE_ITEM with (updlock, holdlock)

Add the holdlock hint to the xlock hint. 将保持锁提示添加到xlock提示。

Eg. 例如。

begin tran 
  select ... from ... with (xlock, holdlock) where ...
commit tran

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM