We have a SQL Server Agent job for loading dumps in case we need to restore from our daily backups. The first step in this job is supposed to kill all connections to the database. However, we frequently encounter a problem where somebody on the network has left an application running which will try to reconnect to the database if disconnected, and so after this first step has completed, this application will reconnect. Therefore, when the restore step comes it fails because it was unable to gain exclusive access to the database.
Usually I would use ALTER DATABASE [db] SET SINGLE_USER WITH ROLL BACK IMMEDIATE
to ensure exclusive access, but unfortunately in this case the application reconnects sooner than the restore begins, and so the restore script is unable to access the database at all.
In order to get around this, I thought that it might be possible to disable all TCP connections during the restore so that only the locally running restore script could access the database. So, my question is is there any way in T-SQL to disable/block TCP connections? Or perhaps is there a way to configure the SQL Server Agent to do this when it starts the job?
Best Answer
If you disable TCP connections to SQL Server, SQL Server Agent might also be disconnected. However, that could be mitigated, and is by default, by enabling the Shared Memory Network Protocol for the server.
Having said that, disabling TCP connectivity is a bit like using a sledgehammer to kill a fly.
Normally, altering the database with
SINGLE_USER WITH ROLLBACK IMMEDIATE
will suffice; however occasionally you run into an application that is especially aggressive at reconnecting, and will reconnect to the database once it is in single user mode, but prior to theRESTORE DATABASE
commencing.One work-around I've used in the past for this is to put the database into
RESTRICTED_USER
mode, as in:I've seen this not work when the app connects as
sa
or some othersysadmin
user. In that case, I've done the following rather more aggressive action:Having the above code in separate SQL Server Agent Job steps is problematic since each statement is executed in a different batch, which takes time to process. Keep that code in a single job step to further reduce the ability for a connection to succeed in between statements.