使用SQL Server作为资源锁定机制

时间:2009-09-05 19:04:07

标签: sql-server-2005 locking resources

给定一个逻辑资源标识符表(每行一个),任意数量的数据库客户端执行以下操作的最佳方法是什么:

  • 声明对特定资源的访问权限(如果尚未声明
  • 选择下一个可用资源并声明它(与上面类似)
  • 发布以前声明的资源

(该表将有一个“claimant”列,在无人认领的行中为NULL。)

我坚持这些操作的原子性:在我为所请求的/下一个可用资源进行SELECT之前我是否需要一个全表锁(以及之后的UPDATE,假设声明成功),或者是否有更多粒度这样做的方法?我现在没有大量的数据,但我更希望尽可能地保持表格的可访问性。

2 个答案:

答案 0 :(得分:3)

您基本上是在描述基于经典队列的工作流程,您应该考虑使用真实的queue

为了便于讨论,以下是您实现目标的方式:

  • 声明特定资源:SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK) WHERE key = @key。如果资源已被声明,将阻止。如果资源已声明,则使用锁定超时返回异常。 <{1}} 必须编入索引并且是唯一的。
  • 下一个可用资源:key。您必须通过定义资源的偏好(最旧,最高优先级等)来定义订单
  • 发布声明的资源:SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK, READPAST) ORDER BY <accessorder>您的交易。

问题的要点是使用正确的锁定提示,这种问题确实需要明确的锁定提示来解决。 UPDLOCK将充当“索赔”锁定。 ROWLOCK创建了正确的粒度,防止服务器“优化”到页面锁定。 READPAST允许您跳过声明的资源。在行上放置UPDLOCK将锁定行并允许您稍后更新它,但会阻止其他操作,例如将在锁定行上阻塞的普通读取提交的SELECT。我的想法是,无论如何你都要更新行,这将产生一个不可避免的X锁定。如果您希望保持桌面更加可用,则可以使用app locks代替,但要更加正确。您需要在资源的字符串描述符上请求应用程序锁定,例如键值,或键的COMMIT或其%%LOCKRES%%值。应用程序锁允许您通过在“会话”范围请求应用程序锁定来将“声明”的范围与事务分开,但是您必须手动释放声明(“事务”范围的应用程序锁在提交时释放) 。不过,有很多方法可以通过app锁射击自己。

答案 1 :(得分:3)

SQL Server有一个名为sp_getapplock的内置存储过程。文档将其描述为

  

锁定应用程序资源。

客户端可以竞争命名锁(您为其指定所需的名称),一旦锁定,请执行所需的操作。客户端崩溃,锁自动释放。要以编程方式释放锁定,您可以致电sp_releaseapplock

使用applocks的可行解决方案

  • 如果申请人为空,请尝试使用相同名称
  • 抓取applock
  • 如果获得了applock,请使用您的claiment id更新该行。
  • 一旦声明了行,请释放applock,因为没有其他客户端会尝试并声明它现已声明
  • 完成后,将claiment更新为null