事务内部更新时,nolock提示不起作用



一个名为Users的表在事务中与其他批次一起更新,当过程进行时,Users表被锁定,即使我使用nolock提示,我也无法从中进行选择

BEGIN TRY 
BEGIN TRANSACTION
---------------------------Apply Users Changes-----------------------------

ALTER TABLE Security.Users NOCHECK CONSTRAINT ALL;

...Other batches
BEGIN
DECLARE @usersCount INT = (SELECT COUNT(1) FROM #xyz),
@batchCount INT = 20,
@batchesDone INT = 0
WHILE @batchesDone * @batchCount < @usersCount
BEGIN
UPDATE Users
SET [UserName] = ISNULL(a.UserName,a.Code),
[Code] = ISNULL(a.[Code], '0'),
[Password] = ISNULL([Password], dbo.HashPassword(ISNULL(a.[Code], '0'))),
[Mobile] = a.[Mobile],
FROM (
SELECT * FROM #xyz
WHERE RN > @batchesDone * @batchCount AND RN <= (@batchesDone + 1) * @batchCount
) a
WHERE Users.Username = a.UserName

SET @batchesDone += 1
END
END 


ALTER TABLE Security.Users CHECK CONSTRAINT ALL;
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT>0
ROLLBACK TRANSACTION
RAISERROR(@message,16,1)
END CATCH

如果我使用nolock,它将挂起,直到程序执行完成

SELECT * FROM Users (NOLOCK)
WHERE LDAPUsername='aaa'

进行

ALTER TABLE Security.Users NOCHECK CONSTRAINT ALL;

如果不进行通信,则需要SQL Server取出表上的架构共享锁,这意味着另一个会话甚至无法生成查询计划。nolock提示不能用于忽略这些。

你可以通过运行自己看到这一点

begin transaction 
ALTER TABLE Security.Users NOCHECK CONSTRAINT ALL;

然后在另一个会话中对security.users进行任何查询,并在另一次会话中使用Adam Machanic的sp_whoisactive过程检查发生了什么(http://whoisactive.com/)。您会看到查询会话正在LCK_M_SCH_S上等待,您可以在其中搜索。

正如我在前面的评论中所解释的,禁用检查约束实际上不太可能对你有好处,我建议你不要这样做。如果你真的想这样做,那么就在显式事务之外调用它,这样它就会立即提交(并允许其他人随意修改数据(。

强制性警告,当您修改正在查看的数据时,nolock可能会给您提供逻辑不一致的数据。

最新更新