SQL Job Agent DB Restore fails with error #6107: Only user processes can be killed - sql-server

We have an SQL Job Agent that runs in the "wee hours" to restore our local database (FooData) from a production backup.
First, the database is set to SINGLE_USER mode and any open processes are killed. Second, the database is restored.
But the 3rd step fails occasionally with Error 6107: "Only User Processes Can Be Killed"
This happens about once or twice a week at seemingly random intervals. Here is the code for step 3 where the failure occasionally occurs:
USE master;
go
exec msdb.dbo.KillSpids FooData;
go
ALTER DATABASE FooData SET MULTI_USER;
go
Does anybody have any ideas what might be occurring to cause this error? I'm thinking there might be some automated process starting up during step 3 or possibly some user trying to log in during that time? I'm not a DBA, so I'm guessing at this point, although I believe that a user should not be able to log in while the DB is in SINGLE_USER mode.

A user probably isn't logged in. The system is probably performing some task. The output of exec sp_who or sp_who2 will show what sessions are open. Any SPID below 50 is a system process, and cannot be killed with KILL. The only way to stop them is to stop the SQL Server service or issue a SHUTDOWN command (which does the same thing).

I found the answer to my problem by changing one line of code which worked like a charm.
As mentioned in the original question, the 'KillSpids" line is used in Step 1 of the job. (Along with SET SINGLE USER) The 'KillSpids' made sense in Step 1 because there may be unwanted processes still active on the database.
The 'KillSpids' line was then added again into Step 3, but it was unnecessary, and was also causing the 6107 error.
I replaced the 'KillSpids' line with the one shown below. Setting the freshly restored database to single user mode takes care of the concern that a user might try to log in before all the job steps have been completed. Here is the updated code:
USE master;
go
ALTER DATABASE [FooData] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
go
ALTER DATABASE FooData SET MULTI_USER;
go

Related

SQL Server Agent Database Restore Job Failure

An SSA database restore job fails sporadically with this error:
String data, right truncation [SQLSTATE 01004]
This job runs daily, and succeeds most of the time. When it fails it is on a Friday and it leaves the database in a restoring state. The code inside the job is the exact same code used for other database restore jobs where this is not a concern.
My solution each time this happens is to delete the database and manually restore it. After manually restoring, I run the job and it runs fine. It continues to run fine every day from that point on until it doesn't.
I checked the SQL logs and I do see this error:
"spid75,Unknown,BackupDiskFile::OpenMedia: Backup device '\the_path_to_the_backups' failed to open. Operating system error 5(Access is denied.).,,,,".
So, I checked to ensure the user has permission to access to the .BAK file at the folder level and the file level. It does have full access.
Any thoughts on how I can stop this job from failing randomly?
EDIT:
This is the code from that job.
USE DBA_Tools;
GO
EXECUTE
DBMaintenance.restoreBackupChain
#BackupFolder = '\\servername\sqlbackups2$\instancename\Database_Backups\DSOG',
#Database = 'DSOG';
USE [DSOG]
GO
EXEC sp_change_users_login 'Auto_Fix', 'reportingServicesUser'
GO
EXEC [DSOG].dbo.sp_changedbowner #loginame = N'sa', #map = false
GO
USE [master] ;
ALTER DATABASE [DSOG] SET RECOVERY SIMPLE ;
GO

Database Keeps Going into Recovery Pending State

I have a SQL server database that has been running perfectly fine on my machine for about 6 months, a couple days ago out of nowhere it was inaccessible (Pending Recovery).
I did a bunch of Googling and have tried the following things to fix the issue but thus far restoring it from a previous backup is the only thing that seems to work.
I have tried (From SMS and SQLCMD):
ALTER DATABASE mydatabase SET EMERGENCY
ALTER DATABASE mydatabase set single_user
DBCC CHECKDB (mydatabase, REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS;
ALTER DATABASE mydatabase set multi_user
Step #3 errors out with: "cannot open mydatabase is already open and can only have one user at a time"
Second try:
EXEC sp_resetstatus 'mydatabase';
ALTER DATABASE mydatabase SET EMERGENCY
DBCC CHECKDB ('mydatabase')
ALTER DATABASE mydatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DBCC CHECKDB ('mydatabase', REPAIR_ALLOW_DATA_LOSS)
ALTER DATABASE mydatabase SET MULTI_USER
Step #5 errors out with the same error.
My question is what could be causing this in the first place and how can I fix it properly without having to do a restore twice a day.
Database is already open and can only have one user at a time, this is error number 924. The complete error message looks like this:
An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)
Msg 924, Level 14, State 1, Line 1 Database ‘db_name’ is already open and can only have one user at a time.
The level 14 belongs to security level errors like a permission denied. It means that it cannot be open because someone is using it.
Use the sp_who or sp_who2 stored procedures. You can also use the kill command to kill the processes that are active in the database.
I also found this thread useful: How to fix Recovery Pending State in SQL Server Database?
what could be causing this in the first place and how can I fix it properly without having to do a restore
The most likely cause is a a hardware or driver problem with your hard disk.
In my case, I had databases set up on my local machine but on an external drive mapped to my hard drive. I have the external drive connected to my docking station all the time but I had to disconnect the hard drive and after I connected it again - the databases that are restored on the external drive went into Recover Pending mode.
In my case what helped me was to set the database offline in Microsoft SQL Server Management Studio by right clicking on the database - Tasks - Take Offline. The status of the database changes to Offline. After that bring the database online again by right clicking on the database - Tasks - Bring online.
The database was successfully recovered without any issues. But if the cause is different these steps may not help.
Take the database offline
Bring the database back online

SQL Server: DB STARTUP blocking processes

I am trying to run
DBCC CHECKTABLE
(or CHECKDB, same result), but I keep getting this error:
Check statement aborted. Database contains deferred transactions.
I've made some researches and found that it's some process with SPID 5 and command DB STARTUP blocks everything. This process is running for a few days already but neither dbcc opentran nor dbcc inputbuffer(5) show anything.
Looks like it just sits there and does nothing.
I've checked the logs for that database and it seems that recovery process went fine (last records are about step 3 of 3 running and that over 500K transactions were rolled back so I assume it's done)
I've tried some advice from Google but none of them helped. Setting database to SINGLE_USER, EMERGENCY and even OFFLINE changed nothing - actually, all of them were blocked in one way or another. I can't restore it from earlier backup for some reasons, and there is no more good advice in Google.
Please help.

Extreme wait-time when taking a SQL Server database offline

I'm trying to perform some offline maintenance (dev database restore from live backup) on my dev database, but the 'Take Offline' command via SQL Server Management Studio is performing extremely slowly - on the order of 30 minutes plus now. I am just about at my wits end and I can't seem to find any references online as to what might be causing the speed problem, or how to fix it.
Some sites have suggested that open connections to the database cause this slowdown, but the only application that uses this database is my dev machine's IIS instance, and the service is stopped - there are no more open connections.
What could be causing this slowdown, and what can I do to speed it up?
After some additional searching (new search terms inspired by gbn's answer and u07ch's comment on KMike's answer) I found this, which completed successfully in 2 seconds:
ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
(Update)
When this still fails with the following error, you can fix it as inspired by this blog post:
ALTER DATABASE failed because a lock could not be placed on database 'dbname' Try again later.
you can run the following command to find out who is keeping a lock on your database:
EXEC sp_who2
And use whatever SPID you find in the following command:
KILL <SPID>
Then run the ALTER DATABASE command again. It should now work.
There is most likely a connection to the DB from somewhere (a rare example: asynchronous statistic update)
To find connections, use sys.sysprocesses
USE master
SELECT * FROM sys.sysprocesses WHERE dbid = DB_ID('MyDB')
To force disconnections, use ROLLBACK IMMEDIATE
USE master
ALTER DATABASE MyDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Do you have any open SQL Server Management Studio windows that are connected to this DB?
Put it in single user mode, and then try again.
In my case, after waiting so much for it to finish I had no patience and simply closed management studio. Before exiting, it showed the success message, db is offline. The files were available to rename.
execute the stored procedure
sp_who2
This will allow you to see if there is any blocking locks.. kill their should fix it.
In SSMS: right-click on SQL server icon, Activity Monitor. Open Processes. Find the processed connected. Right-click on the process, Kill.
In my case I had looked at some tables in the DB prior to executing this action. My user account was holding an active connection to this DB in SSMS. Once I disconnected from the server in SSMS (leaving the 'Take database offline' dialog box open) the operation succeeded.
anytime you run into this type of thing you should always think of your transaction log. The alter db statment with rollback immediate indicates this to be the case. Check this out: http://msdn.microsoft.com/en-us/library/ms189085.aspx
Bone up on checkpoints, etc. You need to decide if the transactions in your log are worth saving or not and then pick the mode to run your db in accordingly. There's really no reason for you to have to wait but also no reason for you to lose data either - you can have both.
Closing the instance of SSMS (SQL Service Manager) from which the request was made solved the problem for me.....
To get around this I stopped the website that was connected to the db in IIS and immediately the 'frozen' 'take db offline' panel became unfrozen.
Also, close any query windows you may have open that are connected to the database in question ;)
I tried all the suggestions below and nothing worked.
EXEC sp_who
Kill < SPID >
ALTER DATABASE SET SINGLE_USER WITH Rollback Immediate
ALTER DATABASE SET OFFLINE WITH ROLLBACK IMMEDIATE
Result: Both the above commands were also stuck.
4 . Right-click the database -> Properties -> Options
Set Database Read-Only to True
Click 'Yes' at the dialog warning SQL Server will close all connections to the database.
Result: The window was stuck on executing.
As a last resort, I restarted the SQL server service from configuration manager and then ran ALTER DATABASE SET OFFLINE WITH ROLLBACK IMMEDIATE. It worked like a charm
In SSMS, set the database to read-only then back. The connections will be closed, which frees up the locks.
In my case there was a website that had open connections to the database. This method was easy enough:
Right-click the database -> Properties -> Options
Set Database Read-Only to True
Click 'Yes' at the dialog warning SQL Server will close all connections to the database.
Re-open Options and turn read-only back off
Now try renaming the database or taking it offline.
For me, I just had to go into the Job Activity Monitor and stop two things that were processing. Then it went offline immediately. In my case though I knew what those 2 processes were and that it was ok to stop them.
In my case, the database was related to an old Sharepoint install. Stopping and disabling related services in the server manager "unhung" the take offline action, which had been running for 40 minutes, and it completed immediately.
You may wish to check if any services are currently utilizing the database.
Next time, from the Take Offline dialog, remember to check the 'Drop All Active Connections' checkbox. I was also on SQL_EXPRESS on local machine with no connections, but this slowdown happened for me unless I checked that checkbox.
SSMS, especially if running it from your own desktop remotely and not directly within the database server, can be a reason for the long delays in detaching a database. For some reason SSMS may not be able to disconnect any existing "connections" to the database.
We found the process was almost instant when we did it directly from the database server itself. And in fact it killed the attempt from my own desktop SSMS session, and it "took over" and detached the database.
Nothing else suggested here worked.
Thanks
In my case i stopped Tomcat server . then immediately the DB went offline .

Test Before Attempting Exclusive Lock

I've written some code to upgrade a SQL Server database. Before I upgrade the database, I attain an exclusive lock via:
ALTER DATABASE Test SET SINGLE_USER WITH NO_WAIT
However, I'd like to test the database to see if the exclusive lock is possible before I run the above code. The test doesn't have to be 100% perfect, I'd just like to avoid the possibility of a timeout when attempting to gain an exclusive lock.
To that end, I've written the code below:
SELECT
*
FROM
sys.db_tran_locks
WHERE
resource_database_id = DB_ID('Test') AND
request_session_id <> ##SPID
I'm assuming that if there's 1 or more row returned, then the database must be in use. Is this true? Or is it not that simple?
UPDATE Taking #gbn's comments into account, I've decided to force rollback of existing connections using the following statement:
ALTER DATABASE Test SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Before running this code, I'll give the user the an opportunity to opt out. However, I'd like the user to be able to see the list of active connections to the database - so they can make an informed decision. Which leads me onto this question.
Mainly, a DB lock is just to show it is in use. Databases don't really have many exclusive locks situations compared to code/table objects.
Single user mode is not a lock, but the number of connections allowed.
I'd wrap the ALTER DATABASE in a TRY/CATCH block because there is no guarantee the state won't change between check and ALTER DB.
However, I could be wrong or misunderstanding the question... so you'll also have to test for the exclusive lock mode on the database resource in the query above. Your code above will show you any lock, which could be someone having a blank query window open in SSMS...
Edit, based on comment
You can detect who is using it by these:
sys.dm_exec_connections
sys.dm_exec_sessions
sys.dm_exec_requests
To be honest, it's difficult to stop auto stats update or a user taking the single connection. Normally, you'd this which disconnects all other users and not bother waiting...
ALTER DATABASE MYDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
What if the database becomes busy from the time you determined that it was not in use, until the point where you try to acquire the exclusive lock?

Resources