sql-server – 在SQL Server中,如何以类似于Oracle的“SELECT FOR UPDATE WAIT”的方式锁定单个行?

前端之家收集整理的这篇文章主要介绍了sql-server – 在SQL Server中,如何以类似于Oracle的“SELECT FOR UPDATE WAIT”的方式锁定单个行?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个连接到Oracle数据库并执行操作的程序.我现在想改编程序也支持sql Server数据库.

在Oracle版本中,我使用“SELECT FOR UPDATE WAIT”来锁定我需要的特定行.我使用它在更新基于SELECT的结果的情况下,其他会话绝对不能同时修改它们,所以他们必须首先手动锁定它.系统高度受限于同时访问相同数据的会话.

例如:
两个用户尝试以优先级最高的方式获取数据库中的行,将其标记为忙,对其执行操作,并将其标记为可用以供将来使用.
在Oracle中,逻辑将基本如此:

BEGIN TRANSACTION;
SELECT ITEM_ID FROM TABLE_ITEM WHERE ITEM_PRIORITY > 10 AND ITEM_CATEGORY = 'CT1'
    ITEM_STATUS = 'available' AND ROWNUM = 1 FOR UPDATE WAIT 5;
UPDATE [locked item_id] SET ITEM_STATUS = 'unavailable';
COMMIT TRANSACTION;

请注意,查询是在我的代码中动态构建的.另请注意,当先前最有利的行被标记为不可用时,第二个用户自动进入下一个,依此类推.此外,不同类别的不同用户不必等待彼此的锁定被释放.最糟糕的是,在5秒钟之后,将返回错误,操作将被取消.

所以最后的问题是:如何在sql Server中实现相同的结果?我一直在看锁定提示,理论上看起来他们应该工作.然而,唯一防止其他锁的锁就是“UPDLOCK”和“XLOCK”,它们只能在表级别工作.
那些在行级别工作的锁定提示都是共享锁,这也不能满足我的需要(两个用户可以同时锁定同一行,并将其标记为不可用,并在相应的项目上执行冗余操作).

有些人似乎添加了一个“时间修改”列,所以会话可以验证它们是修改它的那些,但这听起来就会有很多冗余和不必要的访问.

解决方法

sql Server中有一些锁定提示,但是它们并不跨越其语句,就像您提供的Oracle示例一样.在sql Server中执行此操作的方法是在事务上设置一个包含要执行的语句的隔离级别.请参阅 this MSDN page,但总体结构如下所示:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRANSACTION;

    select * from ...

    update ...

COMMIT TRANSACTION;

SERIALIZABLE是最高的隔离级别.查看其他选项的链接.从MSDN:

SERIALIZABLE Specifies the following:

Statements cannot read data that has been modified but not yet
committed by other transactions.

No other transactions can modify data that has been read by the
current transaction until the current transaction completes.

Other transactions cannot insert new rows with key values that would fall in the range of keys read by any statements in the current transaction until the current transaction completes.

猜你在找的MsSQL相关文章