Tsql 大型过程中的SQL隔离级别或锁

Tsql 大型过程中的SQL隔离级别或锁,tsql,stored-procedures,transactions,Tsql,Stored Procedures,Transactions,我有处理用户操作的大型存储过程 它们由多个select语句组成。这些是经过过滤的,大多数情况下只得到一行。所选内容将复制到可诱惑项中或以其他方式进行计算。 最后,merge语句在数据库中执行所需的更改。 所有内容都封装在一个事务中 我有来自用户的并发输入,select语句的选定行应该被锁定以保持数据完整性 如何锁定所有select语句的选定行,以便在当前事务处理过程中不会通过其他事务更新它们? ROWLOCK和HOLDLOCK的表提示组合是否只锁定选定的行,或者整个表是否因为HOLDLOCK而被

我有处理用户操作的大型存储过程

它们由多个select语句组成。这些是经过过滤的,大多数情况下只得到一行。所选内容将复制到可诱惑项中或以其他方式进行计算。 最后,merge语句在数据库中执行所需的更改。 所有内容都封装在一个事务中

我有来自用户的并发输入,select语句的选定行应该被锁定以保持数据完整性

如何锁定所有select语句的选定行,以便在当前事务处理过程中不会通过其他事务更新它们?

ROWLOCK和HOLDLOCK的表提示组合是否只锁定选定的行,或者整个表是否因为HOLDLOCK而被锁定

SELECT *
FROM dbo.Test    
WITH (ROWLOCK HOLDLOCK ) 
WHERE id = @testId
我可以改用

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
就在交易开始之后?还是把整张桌子都锁上了? 我使用的是SQL2008 R2,但如果SQL2012中的工作方式不同,我也会感兴趣


PS:我刚刚读到关于表提示UPDLOCK和SERIALIZE的内容。UPDLOCK似乎是一种只锁定一行的解决方案,而且似乎UPDLOCK总是锁定而不是ROWLOCK,ROWLOCK只指定如果应用了锁,锁是基于行的。我仍然对解决这个问题的最佳方法感到困惑…

更改隔离级别修复了问题(并锁定在行级别):

下面是我如何测试它的。 我在SQL Management Studio的空白页中创建了一条语句:

begin tran
select 
    *
into #message
from dbo.MessageBody
where MessageBody.headerId = 28

WAITFOR DELAY '0:00:05'

update dbo.MessageBody set [message] = 'message1'
where headerId = (select headerId from #message)

select * from dbo.MessageBody where headerId = (select headerId from #message)

drop table #message
commit tran
在执行此语句时(由于延迟,最后需要5秒),我在另一个窗口中调用了第二个查询:

begin tran

select 
    *
into #message
from dbo.MessageBody
where MessageBody.headerId = 28

update dbo.MessageBody set [message] = 'message2'
where headerId = (select headerId from #message)

select * from dbo.MessageBody where headerId = (select headerId from #message)

drop table #message
commit tran
我很惊讶它是瞬间执行的。这是由于默认的SQL Server事务级别“Read Committed”。由于第一个脚本的更新是在延迟之后完成的,因此在第二个脚本期间还没有提交的更改,因此读取并更新第28行

将隔离级别更改为序列化阻止了这一点,但也阻止了并发-两个SCIPT都是连续执行的

这没问题,因为两个脚本都读取并更改了同一行(通过headerId=28)。在第二个脚本中将headerId更改为另一个值,这些语句并行执行。因此,序列化的锁似乎位于行级别

添加表提示

WITH ( SERIALIZABLE)

在第一个语句的第一个select中,也会阻止对所选行的进一步读取。

您有几个问题,这些问题都包含在文档中。为什么您会认为HOLDLOCK会改变锁?我知道HOLDLOCK强制锁,希望与rowlock结合使用时,只锁定单个行。我澄清了问题,我可以删除问题之后的所有内容,但这可能有助于理解问题。
WITH ( SERIALIZABLE)