We have a script that runs every night, this is the relevant part of the script:
---- Restore DB from file system
print ''
print '----------------------------------------------'
print 'Restoring Database: $(DbName)'
print ''
use master
alter database [$(DbName)] set single_user with rollback immediate
restore database [$(DbName)]
from disk = '$(BackupFile)'
with replace,
move @datalogname TO @datapath,
move @loglogname TO @logpath,
stats = 5
alter database [$(DbName)] set multi_user
alter database [$(DbName)] set new_broker with rollback immediate
print '----------------------------------------------'
Most of the nights it works. On some nights it fails with the following output:
[04:00:29] : [Step 2/7] ----------------------------------------------
[04:00:29] : [Step 2/7] Restoring Database: MYDATABASE
[04:00:29] : [Step 2/7]
[04:00:29] : [Step 2/7] Msg 3101, Level 16, State 1, Server MYSERVER, Line 83
[04:00:29] : [Step 2/7] Exclusive access could not be obtained because the database is in use.
[04:00:29] : [Step 2/7] Msg 3013, Level 16, State 1, Server MYSERVER, Line 83
[04:00:29] : [Step 2/7] RESTORE DATABASE is terminating abnormally.
[04:00:29] : [Step 2/7] Msg 1205, Level 13, State 68, Server MYSERVER, Line 89
[04:00:29] : [Step 2/7] Transaction (Process ID 73) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
[04:00:29] : [Step 2/7] Msg 5069, Level 16, State 1, Server MYSERVER, Line 89
[04:00:29] : [Step 2/7] ALTER DATABASE statement failed.
[04:00:29] : [Step 2/7] ----------------------------------------------
Line 83 is the RESTORE statement. Line 89 is the set multi_user statement.
Why is this happening and how do we make sure it succeeds every time.
UPDATE
No explicit transactions are defined in the script. The script is run with sqlcmd from a file. There are several processes outside of the SQL Server VM that are polling the database regularly, and my guess is that one of them manage to butt in between set single_user and restore when this happens. It was suggested that it can be solved by temporarily enabling a rule on local firewall that prohibits incoming connections, but I'm wondering if there is a SQL only solution.