繁体   English   中英

在SQL Server中更新时如何测试行被锁定

[英]How to test rows are locked while being updated in SQL Server

测试行在更新时是否被锁定的最佳方法是什么?

我有一个查询,该查询选择一个表的前x个记录并更新它们,但是多个工作线程将调用同一查询,因此我想确保此查询已被锁定,如果被锁定,它会抛出某种错误,以便我可以相应地处理它,但我似乎无法抛出一个我可以在.NET(或SQL)中捕获的异常。

查询看起来像:

BEGIN TRANSACTION

UPDATE MyTable WITH (ROWLOCK)
SET x = @X,
    y = @Y,
WHERE ID IN (SELECT TOP 50 ID 
             FROM MyTable
             WHERE Z IS NULL)

SELECT TOP 50 x 
FROM MyTable
WHERE x = @W

COMMIT TRANSACTION

我试图逐步调试SQL中的调试器,以仅调用BEGIN TRANSACTION ,然后从.NET应用程序中调用相同的查询,并期望出现错误,但在.NET中运行良好

所以我的问题是如何生成错误,以便知道当前正在更新记录? 发生这种情况时,我想采取特定的措施,例如以x毫秒重试。

谢谢。

根据您最近的评论(请将此信息添加到您的问题正文中),您只想确保每个线程仅“获取”其他线程无法使用的行。 就像从待处理任务表中选择任务,并确保两个线程都没有选择任何任务。

您正在考虑锁定。 您的问题不是需要摆弄SQL锁定机制的问题。 如果您出于性能原因需要进行调优,则可能会尝试使用锁定,但是远不能确定是否需要这样做。 在此阶段,我什至不理会锁定提示。

您想要做的是在行中有一个字段,该字段指示该行是否被占用,以及被谁占用。 组成的样本T-SQL并没有一致地使用任何内容,但最接近的是Z列。

您需要选择Z具有NULL值(尚未使用)的行。 您显然已经步入正轨。 该字段可以是BIT是/否,并且可以使之起作用(查找UPDATE的OUTPUT子句以了解如何选择选定的行); 但是我怀疑您会发现,对于跟踪/调试而言,仅通过查看数据库即可识别出合并在一起的行,这将更加有用。 我将使用一个可以包含唯一值的列,该值不能同时被任何其他线程使用。

有很多方法。 您可以使用(客户端进程)线程ID或类似名称,但是随着时间的推移会重复执行,这可能是不希望的。 您可以创建一个SQL SEQUENCE并使用这些值,它具有递增的良好功能,但是这会使SQL变得更难理解。 我将使用GUID进行说明。

DECLARE @BatchId AS UNIQUEIDENTIFIER
SET @BatchId = NEWID()
UPDATE MyTable
SET x = @X,
    y = @Y,
    Z = @BatchId
WHERE ID IN (SELECT TOP 50 ID 
             FROM MyTable
             WHERE Z IS NULL)

现在,只有您的一个线程可以使用这些行(当然,假设没有线程欺骗并违反代码模式)。 注意,我什至没有打开显式事务。 在SQL Server中,默认情况下,UPDATE是事务性原子的(它们在隐式事务中运行)。 没有线程可以再次选择这些行,因为在完全提交了UPDATE(对于所有行)之前,不允许任何线程(默认情况下)更新甚至查看这些行。 任何试图同时运行UPDATE的线程都会获得不同的未分配行(取决于锁定提示以及您选择要选择的行的技巧-这是“高级”性能调整的一部分),或者被暂停了几行等待第一个UPDATE完成的毫秒数。

这就是您所需要的。 真。 这些行只属于您自己:

SELECT @BatchId AS BatchId, x 
FROM MyTable
WHERE Z = @BatchId

现在,您的代码从其专用行中获取数据,以及如果需要,可以在以后使用该ID引用同一行的唯一ID(如果确实不需要,请从返回集中取出BatchId)。

如果我对您尝试做的事情的阅读是正确的,则在代码编写完成后,您可能希望通过将另一个字段设置为标志值或时间戳等来标记行。 这样,您将能够确定行是否被“孤立了”,因为行是为了处理而行,但是由于任何原因该进程都死了(在这种情况下,可能需要通过再次将Z设置为NULL来使行再次可用)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM