I have a console application that was written to automatically run several long running scripts. Before running the scripts, it will take a database backup by using the BACKUP DATABASE
command. It will then place the database in single user mode:
ALTER DATABASE databaseName SET SINGLE_USER WITH ROLLBACK IMMEDIATE
The application will then begin running the sql scripts. This part all works great. The problem that I am having is if a script fails, we are doing a restore from the backup taken before beginning the scripts. The reason for this is because a transaction rollback will take far longer than simply doing a restore.
I've tried a few different ways:
-works but periodically gets its connections stolen
USE master RESTORE DATABASE databaseName FROM DISK=N'fileLocation'
-doesn't work, database already in use
EXEC master..sp_executesql N'RESTORE DATABASE databaseName FROM DISK=N''fileLocation'''
I've also tried using the .ChangeDatabase() method of the SqlConnection object (VB.NET). This behaves much the same as the first script above in that it periodically will get it's connection stolen.
In code I am taking pains to ensure I never drop/close my connection and watching the Activity Monitor, it appears that the CHECKPOINT process is what is stealing my connection.
The errors I'm seeing are these:
Database 'databaseName' is already open and can only have one user at a time.
ALTER DATABASE failed because a lock could not be placed on database 'databaseName'. Try again later.
Cannot open database "databaseName" requested by the login. The login failed.
Is there a way to keep CHECKPOINT from stealing my connection?
Best Answer
Your script is failing on the
ALTER DATABASE
not on theRESTORE
. Try setting it toRESTRICTED_USER
first:This script so far has never failed me.
There are two differences to your script. The main difference is that setting the database to
RESTRICTED_USER
first allows the script to get executed even if the database is inSINGLE_USER
to start with.The second is that it drops the database instead of restoring it. You could try to replace the
DROP
with your restore directly, but that might open a new "gap" for something else to sneak in. As you are restoring from a file and not from the database-backup-history, dropping the database first should not be a problem for you. Just execute the restore after the database is gone.