February 16, 2017 by Kenneth Fisher
I had an interesting problem recently. A database was stuck in single user mode. How exactly was it stuck you ask? Well, 4-5 system sessions were holding locks on the database (and blocking each other). Which meant I wasn’t able to get exclusive use of the database which is required to do an ALTER DATABASE to set it back into MULTI_USER.
At this point you may have a couple of questions so let me try to answer (some of) them:
System sessions are those created by SQL itself. They typically (but not always) have session IDs under 50. The best way to tell is that the is_user_process flag in the sys.dm_exec_sessions DMO will be a 0. These sessions include the LOG WRITER, RECOVERY WRITER, TASK MANAGER etc. In my case the problem sessions were all TASK MANAGER sessions.
Why does it matter that they were system sessions? The important thing to remember here is that these sessions can not be KILLed. So because they were holding locks on the database (And somehow even though it was in single user there were multiple sessions with locks in the database. Don’t ask me how.) I wasn’t able to get that exclusive access I needed.
Interestingly when I tried to do the ALTER instead of just hanging I immediately got a deadlock error. I spent a little while trying various things and searching through forums before I went for help on twitter using the #SQLHELP hashtag. After some discussion, it was starting to feel like we were going to have to reboot. Now I don’t know about you but I hate rebooting a server because of a problem like this. It feels like I’m giving up. Finally, though, Robert Davis (b/t) sent me to this link on dba.stackexchange. From what they said, their problem, and quite possibly mine, was caused by the system trying to do an auto statistics update. One of the answers suggested changing the deadlock priority before running a series of ALTERs to set the database OFFLINE, back ONLINE, and then finally back to MULTI_USER mode. Now I decided to simplify things and just changed my deadlock priority then went straight to MULTI_USER. I was able to make the change without any problems and everything moved along smoothly from there.
So what’s can you take out of this? Well, aside from running into my specific problem, which is presumably pretty rare (first time in 20 years for me), it’s an interesting view in resolving a problem. I consider myself reasonably good at T-SQL. And in fact, I did know about deadlock priority ahead of time. But for whatever reason I didn’t put the two together until someone else suggested it. So next time you find yourself stuck on a problem, and you’ve been working on it for a while with no progress, don’t be afraid to reach out for some help.
Update: I just needed this again and realized that I had to skim through a lot of text to find the link to get the answer. In the interest of brevity and not to take anything away from the original answerer (please go upvote their answer, it’s proved HIGHLY useful). Here is the solution:
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE [YourDBName] SET MULTI_USER WITH ROLLBACK IMMEDIATE
In addition on my latest run through of this I had to find and kill the one user connection before any of the above would work. I personally don’t like using sp_who so I used this little query to find the connection.
SELECT db_name(resource_database_id) AS DB_Name, request_session_id FROM sys.dm_tran_locks l WHERE resource_type = 'DATABASE' AND EXISTS (SELECT * FROM sys.dm_exec_sessions s WHERE l.request_session_id = s.session_id AND s.is_user_process = 1) and resource_database_id = db_id('[YourDBName]')