我想实现一个原子事务,如下所示:
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,一个好的解决方案似乎是将事务隔离级别设置为可重复读取。这将确保“在当前事务完成之前,其他事务都不能修改当前事务读取的数据”。
发布于 2009-01-30 20:19:14
实际上,设置事务隔离级别可能比使用查询提示更好。
下面来自联机丛书的参考提供了每种不同隔离级别的详细信息。
http://msdn.microsoft.com/en-us/library/ms173763.aspx
这是一篇很好的文章,解释了SQL Server中的各种类型的锁定行为,并提供了示例。
http://www.sqlteam.com/article/introduction-to-locking-in-sql-server
发布于 2009-01-30 20:29:12
WITH (HOLDLOCK)
允许其他读取器。其他地方建议的UPDLOCK是独占的。
HOLDLOCK将阻止其他更新,但它们可能会使用稍后更新的数据。
UPDLOCK将阻止任何人读取数据,直到您提交或回滚。
您有没有看过sp_getapplock(http://msdn.microsoft.com/en-us/library/ms189823(SQL.90%29.aspx)?,这将允许您序列化这段代码(如果它是唯一的更新位),而不会发生UPDLOCK阻塞
编辑:问题主要在于这段代码在两个不同的会话中运行。使用HOLDLOCk或REPEATABLE_READ,数据将在第一个会话更新之前在第二个会话中读取。使用UPDLOCK,任何人都不能在任何会话中读取数据。
发布于 2009-01-30 20:13:59
我相信这会是UPDLOCK。
https://stackoverflow.com/questions/497049
复制相似问题