Sql-Server

“數據庫正在轉換”錯誤

  • September 10, 2019

今天我試圖在已經存在的數據庫上恢復數據庫,我只需右鍵點擊 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 刪除了數據庫並在新數據庫上恢復。

我的問題是什麼可能導致這種情況?以及如何避免這種情況在未來發生,如果我將來遇到同樣的情況,除了刪除整個數據庫之外,還有其他方法可以解決它嗎???

謝謝

複製品

  1. 打開 SSMS
  2. 在新的查詢視窗中輸入以下內容
use <YourDatabase>;
go
  1. 轉到對象資源管理器(SSMS)並右鍵點擊<YourDatabase>-> Tasks->Take Offline
  2. 打開第二個新的查詢視窗並輸入以下內容:
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_type LCK_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那麼如果您最初確定回滾是可以的,那麼您很可能就足夠了。

引用自:https://dba.stackexchange.com/questions/57432