【问题标题】:Guarantee the lock is exclusive on the table for read also保证锁在表上是独占的以供读取
【发布时间】:2018-03-25 00:43:41
【问题描述】:

我正在编写一个 Web 应用程序,遇到了一个问题,即在列中保留一个仅在两行中相同的值,并且两者都在单批执行中进行。我想出了一种解决方案来读取列中的 MAX 值并递增 1。因此,我最终编写了锁定表的过程,以便其他用户不应该得到 MAX 值的脏读。

Create table D(Id int , Name varchar(100))

Begin Tran 
    DECLARE @i int = (SELECT MAX(ID) FROM D with (tablockx, holdlock))
    Print @i ;

    Insert into D values ((@i + 1), 'ANAS')

    SELECT * FROM D 

    --COMMIT 
Rollback 

此代码锁定表,直到查询提交或回滚。我对此有两个问题 1)此代码是否保证对表具有排他锁? 2)在我的快速阅读中,tablockx 也可以帮助执行锁定读取,而 holdlock 有助于防止我在锁定会话中工作的行中的更改,但这是否正确使用,因为我认为 holdlock 实际上可能不需要

【问题讨论】:

  • 这闻起来像XY Problem。使用OUTPUT 子句从由 other 语句操作的行中获取任何数据可能更有意义,例如新插入行的标识列值。 (OUTPUT 可以与 INSERTUPDATEDELETEMERGE 一起使用,并在以下情况下提供对 beforeafter 值的访问UPDATE。)然后将这些数据重用于INSERT

标签: sql-server-2008 tsql


【解决方案1】:

不确定您提出的问题是否正确。您需要不更改当前值并且不插入。使用 SERIALIZABLE,您可能不需要(updlock)。

我对这个答案并不肯定。您应该自己进行测试。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
Begin Tran 
    DECLARE @i int = (SELECT MAX(ID) FROM D with (updlock))
    Print @i ;

    Insert into D values ((@i + 1), 'ANAS')

    SELECT * FROM D 

    --COMMIT 
Rollback

身份或序列号是更好的方法

【讨论】:

  • @paparazo 因为身份和序列将按间隔递增(比如说+1),这并不能解决问题,因为所有行都有自己的唯一值。正如帖子中提到的那样,我希望单列的两行中的值相同,这将增加假设每次添加接下来的两行时增加 +1,然后新添加的行在这两个行中将具有相似的相同值。
  • @Anas Sure 听起来像是一个有问题的数据设计
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-11
  • 2010-09-22
  • 2023-01-10
  • 2014-01-16
  • 1970-01-01
  • 2014-08-11
相关资源
最近更新 更多