在 MS SQL Server 上使用 sp_getapplock 来防止应用程序的多个实例同时运行

问题描述 投票:0回答:1

考虑一个不支持水平缩放的应用程序。基本上,如果应用程序的 2 个或更多实例同时运行,就会发生不好的事情(例如:应用程序状态已损坏)。 该应用程序通过使用调度程序来执行。在每次迭代中,调度程序都会启动应用程序,处理一些工作项,然后应用程序退出。一段时间后,调度程序将再次触发,并完成应用程序的新执行。这将无限期地重复。例如,您可以想象此应用程序的每小时时间表。

我们正在考虑在应用程序级别添加一些逻辑的可能性,以防止多个实例同时运行的可能性。有多种方法可以做到这一点,我们考虑的一种可能性是使用这个分布式锁库

我能想到的在这种情况下使用分布式锁的最简单方法如下:

  1. 当应用程序启动时,就会尝试获取锁
  2. 如果尝试获取锁失败,则说明已经有一个应用程序实例在运行。在这种情况下,进程会记录一条消息并退出。
  3. 如果尝试获取锁成功,则意味着当前实例是唯一正在运行的实例,因此应用程序可以继续进行处理。完成后,分布式锁被释放,进程退出。

请注意,通过这样做,我们将整个应用程序执行视为受分布式锁保护的关键部分。这意味着在完成单个应用程序执行所需的整个时间内,该锁将由正在运行的应用程序实例持有。 我们假设这个时间是 15 分钟的数量级。

我们想要使用的分布式锁实现是基于 SQL Server 的分布式锁实现。在底层,此实现利用 sp_getapplock

 来实现 SQL Server 的分布式锁。
由于我对 SQL Server 没有太多经验,而且以前从未使用过 sp_getapplock
,所以我问自己在执行此类操作时是否存在任何已知问题。例如:对 SQL Server 实例的性能有影响吗?对于访问同一个数据库的其他应用程序和查询,我是否会遇到任何缓慢和/或死锁的情况?长时间持有这样的锁会对数据库资源产生任何负面影响(例如:减少服务传入查询的资源)?

请注意,我的想法是使用

Session 作为锁所有者。我希望避免 15 分钟的持久事务,因此我更愿意使用 Session

 作为锁所有者值,而不是 
Transaction
。你觉得这有什么问题吗?

重要提示:我提到分布式锁库只是为了向阅读此问题的任何人提供一些上下文和背景信息。这个问题的目的不是为了获得有关该库的使用的任何指导或意见。在这里,我只是研究 Microsoft SQL Server 中 sp_getapplock 存储过程的用法。我的问题的核心是了解数据库级别的任何可能的影响,因为如上所述,我不是该领域的专家,而且我以前从未使用过 sp_getapplock。

c# sql sql-server concurrency locking
1个回答
0
投票
sp_applock 使用 SQL Server 的普通锁定行为。所以

例如:对 SQL Server 实例的性能有影响吗?

不。锁很便宜,而且 SQL Server 可以管理大量锁。

长期会话需要一点内存,但管理数百或数千个会话并不是什么大问题。

我可以预期访问同一数据库的其他应用程序和查询会出现任何缓慢和/或死锁吗

这取决于您在持有应用锁时执行的操作,但与应用锁本身无关。

您发现【使用Session作为锁拥有者】有什么问题吗?

唯一的问题是,将孤立的应用程序锁保留为会话所有权会更容易。如果您设置 XACT ABORT 并使用事务作为所有者,则连接上的错误将可靠地释放应用程序锁。

如果拥有应用程序锁的会话没有执行大量您不希望参与长期事务的其他数据库工作,那么会话所有权和事务所有权之间没有真正的区别。

© www.soinside.com 2019 - 2024. All rights reserved.