Alter database Set Single_User
對於任何DBA來說,恐怕都不陌生。在我們需要獲取資料庫獨佔訪問權來做一些資料庫緊急維護的時候,這可能是大多數DBA的首選,但它真的可以實現“獨佔訪問權”嗎?
這次我們聊聊Single_User是如何重新整理我們認知的
==============華麗麗的分割線==============
實驗目的:測試Single_User模式下是否可以拿到獨佔權併為所欲為。
照例交代一下我們的環境:Windows 10 + SQL Server 2019,實際上本次實驗的結果基本上是覆蓋SQL Server全部版本的
併發測試工具:SQLQueryStress(0.9.7.79)
我們先看一下在單使用者模式下,持有鎖的情況
從上圖可以看到,在成功置為Single_User模式後,我們擁有了一個執行Session(id=60)上,DB級別的S鎖
這時,我們開啟SQLQueryStress,設定查詢語句,併發執行緒數為2,迭代5000次
再次查詢持有鎖的情況
Session 71、72是我們壓力測試工具設定2個執行緒產生的,可以看到,除了持有S鎖外,他們各自還正在申請X鎖,只是相互等待而形成了死鎖
由上圖可以看到,XEvents中存在大量死鎖資訊,且下圖可以看到死鎖的細節資訊,由Session 71、72導致
此時,當我們再次準備從Session 60中執行語句,將資料庫置為Multi_User時,錯誤發生了:
Session 60也被死鎖犧牲了。由此看來,我們並沒有真正的獲取資料庫的“獨佔訪問權”
==============華麗麗的分割線==============
分析 & 結論:
1、將資料庫置為單使用者模式在我們長期的認知中,都是絕對的“獨佔訪問權”。但實際上,在有併發+連續訪問的情況下,我們仍有可能因外部訪問的死鎖而丟掉這個“獨佔訪問權”
2、進一步分析,從將資料庫置為單使用者模式的時候,資料庫系統沒有直接將Session的鎖級別提升至最高(個人理解,從Alter Database觸發的動作,置為SCH-X都不為過),而是溫和的放置了DB級的S鎖,同時對其他訪問相同資料庫的請求則要求申請X鎖,這就導致了,當外部請求訪問資料庫時,先放置DB級S鎖(這裡和Single User Session 的DB級S鎖且相容),而後因為要申請X鎖,所以和其他訪問同樣資料庫的請求達成了死鎖條件。
3、如果在應急處置中仍需要將DB置為Single User模式,建議停掉外部訪問(停賬號,修改例項埠號,關閉TCP\IP,禁用外部訪問網路卡,或者修改資料庫名稱),以免無法置回Multi User模式。