给定一个逻辑资源标识符表(每行一个),任意数量的数据库客户端执行以下操作的最佳方法是什么:
(该表将有一个“claimant”列,在无人认领的行中为NULL。)
我坚持这些操作的原子性:在我为所请求的/下一个可用资源进行SELECT之前我是否需要一个全表锁(以及之后的UPDATE,假设声明成功),或者是否有更多粒度这样做的方法?我现在没有大量的数据,但我更希望尽可能地保持表格的可访问性。
答案 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的可行解决方案