迷之自信的Single_User Mode

Alter database Set Single_User数据库

对于任何DBA来讲,恐怕都不陌生。在咱们须要获取数据库独占访问权来作一些数据库紧急维护的时候,这多是大多数DBA的首选,但它真的能够实现“独占访问权”吗?并发

此次咱们聊聊Single_User是如何刷新咱们认知的工具

==============华丽丽的分割线==============测试

实验目的:测试Single_User模式下是否能够拿到独占权并随心所欲。spa

照例交代一下咱们的环境:Windows 10 + SQL Server 2019,实际上本次实验的结果基本上是覆盖SQL Server所有版本的线程

并发测试工具:SQLQueryStress(0.9.7.79)blog

咱们先看一下在单用户模式下,持有锁的状况io

从上图能够看到,在成功置为Single_User模式后,咱们拥有了一个执行Session(id=60)上,DB级别的S锁压力测试

这时,咱们开启SQLQueryStress,设置查询语句,并发线程数为2,迭代5000次请求

再次查询持有锁的状况

Session 7一、72是咱们压力测试工具设置2个线程产生的,能够看到,除了持有S锁外,他们各自还正在申请X锁,只是相互等待而造成了死锁

由上图能够看到,XEvents中存在大量死锁信息,且下图能够看到死锁的细节信息,由Session 7一、72致使

 

此时,当咱们再次准备从Session 60中执行语句,将数据库置为Multi_User时,错误发生了:

Session 60也被死锁牺牲了。由此看来,咱们并无真正的获取数据库的“独占访问权”

 

==============华丽丽的分割线==============

分析 & 结论:

一、将数据库置为单用户模式在咱们长期的认知中,都是绝对的“独占访问权”。但实际上,在有并发+连续访问的状况下,咱们仍有可能因外部访问的死锁而丢掉这个“独占访问权”

二、进一步分析,从将数据库置为单用户模式的时候,数据库系统没有直接将Session的锁级别提高至最高(我的理解,从Alter Database触发的动做,置为SCH-X都不为过),而是温和的放置了DB级的S锁,同时对其余访问相同数据库的请求则要求申请X锁,这就致使了,当外部请求访问数据库时,先放置DB级S锁(这里和Single User Session 的DB级S锁且兼容),然后由于要申请X锁,因此和其余访问一样数据库的请求达成了死锁条件。

三、若是在应急处置中仍须要将DB置为Single User模式,建议停掉外部访问(停帐号,修改实例端口号,关闭TCP\IP,禁用外部访问网卡,或者修改数据库名称),以避免没法置回Multi User模式。