Consider an application which is designed in such a way that horizontal scaling is not supported. Basically, if 2 or more instances of the application run at the same time bad things happen (e.g.: the application state is corrupted). This application is executed by using a scheduler. At each iteration the scheduler starts the application, some work items are processed and then the application exits. Some time later the scheduler will fire again and a new execution of the application will be done. This will be repeated indefinitely. As an example, you can imagine an hourly schedule for this application.
We are considering the possibility to add some logic at the application level to guard against the possibility of multiple instances running concurrently. There are several ways to do so, one possibility we considered is using this distributed lock library
The simplest way I can think of using a distributed lock in this context is the following one:
- when the application starts, an attempt to acquire the lock is done
- if the attempt to acquire the lock fails, then it means there is already an application instance running. In this case the process logs a message and exits.
- if the attempt to acquire the lock succeeds, then it means the current instance is the only one running, so the application can continue doing its processing. When it is done, the distributed lock is released and the process exits.
Notice that, by doing so, we are considering the entire application execution as the critical section protected by the distributed lock. This means that the lock will be held by the running instance of the application for the entire time required to complete one single application execution. Let's assume that this time is in the order of magnitude of 15 minutes.
The distributed lock implementation we would like to use is the one based on SQL Server . Under the hood, this implementation makes use of sp_getapplock
to implement the distributed lock with SQL Server. Since I don't have a lot of experience with SQL Server and I've never used sp_getapplock
before, I'm asking myself if there is any known issue in doing something like this. For instance: is there any impact performance-wise on the SQL Server instance ? Can I expect any slowness and / or deadlock for other applications and queries accessing the very same database ? Holding such a lock for a long time can have any negative impact on database resources (e.g.: reduced resources to serve incoming queries) ?
Please, notice that the idea I have is to use Session as the lock owner. I would like to avoid having a long lasting transaction of 15 minutes, so I would prefer using Session
as the lock owner value instead of Transaction
. Do you see any problem with this ?
Important note: I mentioned the distributed lock library only to give some context and background information to anyone reading this question. The purpose of this question is not to get any guidance or opinion on the usage of that library. Here I'm just investigating the usage of the sp_getapplock stored procedure in Microsoft SQL Server. The core of my question is understanding any possibile impact at the database level, since as explained above I'm not an expert on that field and I have never used sp_getapplock before.
1条答案
按热度按时间v6ylcynt1#
sp_applock uses SQL Server's ordinary locking behavior. So
For instance: is there any impact performance-wise on the SQL Server instance ?
No. Locks are cheap, and SQL Server can manage a large number of them.
The long-lived session requires a bit of memory, but managing hundreds or a few thousand sessions isn't a big deal.
Can I expect any slowness and / or deadlock for other applications and queries accessing the very same database
This depends on what you do while holding the app lock, but has nothing to do with the app lock itself.
Do you see any problem with [using Session as the lock owner]?
The only problem with that is that it's easier to leave an orphaned app lock with session ownership. If you SET XACT ABORT on and use a transaction as the owner, then errors on the connection will reliably release the app lock.
If the session that owns the app lock is not doing a bunch of other database work that you don't want to enlist in a long-lived transaction, then there's no real difference between session ownership and transaction ownership.