我应该使用哪些锁提示(T-SQL)?

我应该使用哪些锁提示(T-SQL)?,sql,sql-server,tsql,concurrency,locking,Sql,Sql Server,Tsql,Concurrency,Locking,我希望实现如下所示的原子事务: BEGIN TRAN A SELECT id FROM Inventory WITH (???) WHERE material_id = 25 AND quantity > 10 /* Process some things using the inventory record and eventually write some updates that are dependent on the fact that that specific inven

我希望实现如下所示的原子事务:

BEGIN TRAN A

SELECT id
FROM Inventory
WITH (???)
WHERE material_id = 25 AND quantity > 10

/*
Process some things using the inventory record and
eventually write some updates that are dependent on the fact that
that specific inventory record had sufficient quantity (greater than 10).
*/

COMMIT TRAN A
问题是,发生的其他事务会消耗我们库存中的数量,因此在选择记录和在事务A中写入更新之间,该记录可能会成为无效选择,因为它的数量可能已降低到WHERE子句中的阈值以下

因此,问题是我应该在WITH子句中使用什么锁定提示来防止在完成更新和提交事务之前更改所选的库存记录

编辑:
多亏了John,一个好的解决方案似乎是将事务隔离级别设置为可重复读取。这将确保“在当前事务完成之前,没有其他事务可以修改当前事务读取的数据。”

我相信这将是UPDLOCK

锁定提示:

WITH (UPDLOCK, HOLDLOCK)

实际上,您最好设置事务隔离级别,而不是使用查询提示

以下来自联机丛书的参考资料提供了每个不同隔离级别的详细信息

这是一篇很好的文章,解释了SQL Server中各种类型的锁定行为,并提供了一些示例

WITH(HOLDLOCK)
允许其他读卡器。 其他地方建议的UPDLOCK是独占的

HOLDLOCK将阻止其他更新,但它们可能会使用稍后更新的数据

UPDLOCK将阻止任何人读取数据,直到您提交或回滚

你看过吗? 这将允许您序列化此代码(如果它是唯一的更新位),而无需UPDLOCK阻塞

编辑:问题主要在于这段代码在两个不同的会话中运行。 使用HOLDLOCk或REPEATABLE_READ,数据将在第一次会话更新之前的第二次会话中读取。使用UPDLOCK,任何人都无法在任何会话中读取数据。

MSSQL:

SELECT id
FROM Inventory (UPDLOCK)
WHERE material_id = 25 AND quantity > 10;

http://www.devx.com/tips/Tip/13134


您可能对PostgreSQL感兴趣:

SELECT id
FROM Inventory    
WHERE material_id = 25 AND quantity > 10
FOR UPDATE;

请记住,在SQLServer2005及更高版本中,锁定不会以这种方式运行。这篇文章已经过时了。那么你会建议使用可重复读取隔离级别吗?是的,这肯定会奏效。为了将来参考,您可能希望了解SQL Server中使用行版本控制的其他可用隔离级别。这是一个很难理解但很有价值的知识,回答很好-我们在设置StackOverflow DB时查阅了所有隔离级别文档。我唯一担心的是设置隔离级别会影响系统中运行的所有事务。由于此特定事务相对较慢,因此事务级别将在一段时间内可重复读取。因此,其他不需要此protectionlevel的事务可能会开始阻塞,系统的并发性将降低。要确保没有其他进程可以读取此数据,并且在trando updlock期间它将保留此数据,请打开另一个窗口,并对同一个tabledoh执行选择!当然更新锁不是独占锁。但不确定是否需要它。。。这取决于你如何理解问题好的问题。。。我很快就要编写一些完全符合这个标准的代码了。。。我甚至没有意识到这是一个问题:)谢谢安德鲁!是的,我突然想到,如果数据或事务使用的假设在处理过程中发生更改,则事务实际上不会产生一致的结果。问题不是在会话a执行事务时试图阻止Seision B读取数据。问题是阻止会话B写入会话A的事务在其计算中使用的行,以防止计算使用过时的data.holdlock。允许读,但不允许写。或者将所有数据加载到本地变量/表变量中