“數據庫正在轉換”錯誤
今天我試圖在已經存在的數據庫上恢復數據庫,我只需右鍵點擊 SSMS 中的數據庫 –> 任務 –> 離線,這樣我就可以恢復數據庫。
一個小的彈出視窗出現並顯示
Query Executing.....
了一段時間,然後拋出一個錯誤說Database is in use cannot take it offline
。我從中收集到該數據庫的一些活動連接,因此我嘗試執行以下查詢USE master GO ALTER DATABASE My_DatabaseName SET OFFLINE WITH ROLLBACK IMMEDIATE GO
再次在這一點上,SSMS 顯示
Query Executing.....
了一段時間,然後拋出以下錯誤:Msg 5061, Level 16, State 1, Line 1 ALTER DATABASE failed because a lock could not be placed on database 'My_DatabaseName'. Try again later. Msg 5069, Level 16, State 1, Line 1 ALTER DATABASE statement failed.
在此之後,我無法通過 SSMS 連接到數據庫。當我嘗試使用 SSMS 使其離線時,它拋出了一個錯誤消息:
Database is in Transition. Try later .....
在這一點上,我根本無法觸及數據庫,我嘗試過的任何操作都返回了相同的錯誤消息
Database is in Transition
。我在Google上閱讀了一些人們遇到類似問題的問題,他們建議關閉 SSMS 並再次打開它,我也是,因為它只是一個開發伺服器,我剛剛使用 SSMS 刪除了數據庫並在新數據庫上恢復。
我的問題是什麼可能導致這種情況?以及如何避免這種情況在未來發生,如果我將來遇到同樣的情況,除了刪除整個數據庫之外,還有其他方法可以解決它嗎???
謝謝
複製品
- 打開 SSMS
- 在新的查詢視窗中輸入以下內容
use <YourDatabase>; go
- 轉到對象資源管理器(SSMS)並右鍵點擊
<YourDatabase>
->Tasks
->Take Offline
- 打開第二個新的查詢視窗並輸入以下內容:
use <YourDatabase>; go
系統將提示您以下消息:
消息 952,級別 16,狀態 1,第 1 行
數據庫“TestDb1”正在轉換。稍後嘗試該語句。
發生這種情況的原因可以從與以下類似的診斷查詢中找到:
select l.resource_type, l.request_mode, l.request_status, l.request_session_id, r.command, r.status, r.blocking_session_id, r.wait_type, r.wait_time, r.wait_resource, request_sql_text = st.text, s.program_name, most_recent_sql_text = stc.text from sys.dm_tran_locks l left join sys.dm_exec_requests r on l.request_session_id = r.session_id left join sys.dm_exec_sessions s on l.request_session_id = s.session_id left join sys.dm_exec_connections c on s.session_id = c.session_id outer apply sys.dm_exec_sql_text(r.sql_handle) st outer apply sys.dm_exec_sql_text(c.most_recent_sql_handle) stc where l.resource_database_id = db_id('<YourDatabase>') order by request_session_id;
對於它的價值,您不需要對象資源管理器來重現此錯誤。您只需要一個嘗試相同操作的被阻止請求(在這種情況下,使數據庫離線)。有關 T-SQL 中的三個步驟,請參見以下螢幕截圖:
您最有可能看到的是您的對象資源管理器會話被另一個會話阻止(由 顯示
blocking_session_id
)。該對象資源管理器會話將嘗試獲取X
數據庫上的排他鎖 ( )。在上述重現的情況下,對象資源管理器會話被授予更新鎖 (U
) 並嘗試轉換為排他鎖 (X
)。它有一個 wait_typeLCK_M_X
,被第一個查詢視窗表示的會話阻塞(在數據庫上獲取use <YourDatabase>
共享鎖 (S
))。然後這個錯誤來自另一個試圖獲得鎖的會話,並且這個錯誤消息導致會話拒絕訪問試圖轉換到不同狀態的數據庫(在這種情況下,線上狀態到離線過渡)。
下次你應該怎麼做?
首先,不要驚慌,也不要開始刪除數據庫。您需要採取故障排除方法(使用與上述類似的診斷查詢)來找出您看到的*原因。*有了這樣的消息,或者當某些東西出現“掛起”時,您應該自動假設缺乏並發性並開始深入研究阻塞(
sys.dm_tran_locks
這是一個好的開始)。作為旁注,我真的相信你最好在採取任何隨機行動之前找出問題的根源。不僅是這個操作,而且適用於所有你不期望的行為。知道是什麼真正導致了你的問題,很明顯這真的沒什麼大不了的。你基本上有一個阻塞鏈,而父阻塞器是你很可能剛剛發出的
KILL
,或者如果它是你不想要的會話請求,KILL
那麼你可以等到它完成。無論哪種方式,您都知道根據您的特定情況(回滾或等待送出)做出正確和謹慎的決定。另一件值得注意的事情,這是我總是選擇 T-SQL 替代方案而不是 GUI 的原因之一。您確切地知道您正在使用 T-SQL 執行什麼以及 SQL Server 在做什麼。畢竟,您發出了明確的命令。當您使用 GUI 時,實際的 T-SQL 將是一個抽象。在這種情況下,我查看了被阻止的對象資源管理器嘗試使數據庫離線,結果是
ALTER DATABASE <YourDatabase> SET OFFLINE
. 沒有嘗試回滾,這就是它無限期等待的原因。在您的情況下,如果您想回滾在該數據庫上鎖定的會話,ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATE
那麼如果您最初確定回滾是可以的,那麼您很可能就足夠了。