我有一个连接到Oracle数据库并对其执行操作的程序.现在我想调整该程序,使其也支持SQL Server数据库.

在Oracle版本中,我使用" Select 更新等待"来锁定所需的特定行.我在更新基于SELECT结果的情况下使用它,而其他会话绝对不能同时修改它,因此它们必须先手动锁定它.该系统极易受到试图同时访问相同数据的会话的影响.

例如:
两个用户try 获取数据库中具有最高优先级的行,将其标记为忙碌,对其执行操作,然后将其再次标记为可供以后使用. 在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;

请注意,查询是在我的代码中动态生成的.还要注意的是,当之前最有利的一行被标记为不可用时,第二个用户将自动 Select 下一行,以此类推.此外,从事不同类别工作的不同用户不必等待对方的锁被释放.最糟糕的情况是,5秒钟后,将返回一个错误,操作将被取消.

因此,最后一个问题是:如何在SQL Server中实现相同的结果?我一直在研究锁定提示,从理论上讲,它们似乎应该起作用.但是,唯一可以阻止其他锁的锁是"UPDLOCK"和"XLOCK",这两个锁都只能在表级工作.
那些在行级工作的锁定提示都是共享锁,也不能满足我的需求(两个用户可以同时锁定同一行,都将该行标记为不可用并对相应的项执行冗余操作).

有些人似乎添加了一个"time Modified"列,这样会话就可以验证是他们修改了它,但这听起来似乎会有很多冗余和不必要的访问.

推荐答案

在SQL Server中有锁定提示,但它们不像您提供的Oracle示例那样跨越它们的语句.在SQL Server中实现这一点的方法是在包含要执行的语句的事务上设置隔离级别.参见this MSDN page,但总体 struct 如下所示:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRANSACTION;

    select * from ...

    update ...

COMMIT TRANSACTION;

SERIALIZABLE是最高隔离级别.有关其他选项,请参阅链接.来自MSDN:

SERIALIZABLE指定以下内容:

语句无法读取已修改但尚未修改的数据

任何其他事务都不能修改已由

其他事务无法插入键值为

Database相关问答推荐

如何将对象源动态设置为子窗体

MongoDB根据嵌套文档中的值匹配数组

当某些 node 死亡时,mongo 副本集选举如何表现?

Select 正确的数据库:MySQL 与Everything 其它数据库

Objective-C中是否有类似于LINQ的东西?

便携式(PHPPass)密码哈希.我应该使用它们吗?

为什么 DynamoDB 查询中没有**not equal**比较?

将整数作为字符串存储在数据库中的缺点

SQLite3 的动态类型

通过删除执行计划中的排序运算符来优化 SQL 查询

如何在 Play 2.0 中 for each 环境设置不同的数据库?

免费的便携式数据库有哪些?

Meteor 如何执行数据库迁移?

为什么在连接表上有一个主键不好?

如果数据库已经提供缓存,为什么还要使用应用程序级缓存?

找不到类型或命名空间名称SQLConnection

将文本列设为唯一键

App=EntityFramework 在 Sql 连接字符串中有什么作用?

字符串列上的postgresql索引

在一个查询中使用 group by 计算多列