在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”,它们只能在表级别工作.
那些在行级别工作的锁定提示都是共享锁,这也不能满足我的需要(两个用户可以同时锁定同一行,并将其标记为不可用,并在相应的项目上执行冗余操作).
解决方法
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.