【问题标题】:Which lock hints should I use (T-SQL)?我应该使用哪些锁定提示 (T-SQL)?
【发布时间】:2009-01-30 20:10:51
【问题描述】:

我想实现一个原子事务,如下所示:

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,一个好的解决方案似乎是将事务隔离级别设置为 REPEATABLE READ。这将确保“在当前事务完成之前,没有其他事务可以修改当前事务已读取的数据。”

【问题讨论】:

  • 好问题...我很快就会编写一些完全符合此标准的代码...我什至没有意识到这是一个问题:)
  • 谢谢安德鲁!是的,我突然想到,如果数据或交易使用的假设在处理过程中发生了变化,那么交易并没有真正产生一致的结果。

标签: sql sql-server tsql concurrency locking


【解决方案1】:

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

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

http://msdn.microsoft.com/en-us/library/ms173763.aspx

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

http://www.sqlteam.com/article/introduction-to-locking-in-sql-server

【讨论】:

  • 那么你会建议使用 REPEATABLE READ 隔离级别吗?
  • 是的,这肯定会奏效。为了将来参考,您可能希望了解 SQL Server 中使用行版本控制的其他可用隔离级别。这是一本很难读但很有价值的知识,msdn.microsoft.com/en-us/library/ms345124.aspx
  • 不错的答案 - 我们在设置 StackOverflow 数据库时查看了所有隔离级别文档。
  • 我唯一担心的是设置隔离级别会影响系统中运行的所有事务。由于此特定事务将相对较慢,因此事务级别将在一段时间内处于可重复读取状态。所以其他不需要的交易确实需要这种保护
  • 级别可能会开始阻塞,系统的并发性会降低。
【解决方案2】:

table hints

WITH (HOLDLOCK) 允许其他读者。 其他地方建议的 UPDLOCK 是专有的。

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

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

你看过sp_getapplock吗? 这将允许您在没有 UPDLOCK 阻塞的情况下序列化此代码(如果它是唯一的更新位)

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

【讨论】:

  • 问题不是试图阻止 Seesion B 在会话 A 执行事务时读取数据。问题是阻止会话 B 写入会话 A 的事务在其计算中使用的行,以防止计算使用过时的数据。
  • 然后锁定。允许读但不允许写。或者将所有数据加载到本地变量/表变量中
【解决方案3】:

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;

【讨论】:

    【解决方案4】:

    我相信这将是 UPDLOCK。

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

    【讨论】:

    • 请记住,在 SQL Server 2005 及更高版本中锁定不会以这种方式运行。这篇文章已经过时了。
    【解决方案5】:

    锁定提示:

    WITH (UPDLOCK, HOLDLOCK)
    

    【讨论】:

    • 以确保没有其他进程甚至可以读取此文件,并且它将在 tran 期间保持它
    • 做updlock,然后打开另一个窗口并对同一个表做一个选择
    • 哇!当然。更新锁不是排他锁。不确定是否需要...这取决于您如何阅读问题
    猜你喜欢
    • 1970-01-01
    • 2011-04-23
    • 2010-11-26
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多