「データベースは移行中です」エラー


12

今日、既存のデータベースの上にデータベースを復元しようとしていましたが、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

私は人々が同様の問題に直面していたいくつかの質問をグーグルで読みました、そして彼らはSSMSを閉じて再び開くことを勧めました、そして私もそうしました、そしてそれは単なる開発サーバーだったので、SSMSを使用してデータベースを削除し、新しいデータベースに復元しました。

私の質問は、これを引き起こした可能性のあるものは何ですか?そして、どうすればこれが将来発生するのを回避できますか?私が将来同じ状況に陥った場合、それを修正してデータベース全体を削除する他の方法はありますか?

ありがとうございました

回答:


23

再現

  1. SSMSを開く
  2. 新しいクエリウィンドウに次のように入力します

    use <YourDatabase>;
    go
  3. オブジェクトエクスプローラー(SSMS)に移動し、右クリック<YourDatabase>-> Tasks->Take Offline
  4. 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の3つのステップについては、以下のスクリーンショットを参照してください。

ここに画像の説明を入力してください

最もよく表示されるのは、オブジェクトエクスプローラーセッションが別のセッション(で示されているblocking_session_id)によってブロックされていることです。そのオブジェクトエクスプローラーセッションはX、データベースの排他ロック()を取得しようとします。上記の再現のケースでは、オブジェクトエクスプローラーセッションに更新ロック(U)が付与され、排他ロック(X)に変換しようとしました。LCK_M_X最初のクエリウィンドウ(データベースのuse <YourDatabase>共有ロック(S)を取得)で表されるセッションによってブロックされたwait_typeがありました。

そして、このエラーは、ロックを取得しようとしているさらに別のセッションから発生し、このエラーメッセージは、別の状態(この場合はオンラインの状態)に移行しようとしているデータベースへのアクセスを取得するセッションの拒否を引き起こしますオフライン移行へ)。

次回はどうしますか?

まず、パニックになったり、データベースの削除を開始したりしないください。あなたは見つけるために(上記のような類似した診断クエリで)トラブルシューティングのアプローチを取る必要があり、なぜあなたは何をしているシーイング見ています。そのようなメッセージがある場合、または何かが「ハング」しているように見える場合は、並行性の欠如を自動的に想定し、ブロッキングの調査を開始する必要があります(これsys.dm_tran_locksは良いスタートです)。

余談ですが、ランダムなアクションをとる前に、問題の根源を見つけることが最善であると私は本当に信じています。この操作だけでなく、それは予期しないすべての動作に当てはまります。何が本当に問題を引き起こしているかを知っていれば、それが本当に大した問題ではなかったことは明らかです。基本的にはブロッキングチェーンがあり、親ブロッカーはおそらくKILLonを発行した可能性が高いものでした。または、セッションの要求でありたくない場合はKILL、完了するまで待機することもできます。どちらの方法でも、特定のシナリオ(ロールバックまたはコミットの待機)を考慮して、適切かつ慎重な決定を行うための知識がありました。

注目に値するもう1つのことは、これが常にGUIではなくT-SQLの代替案を選択する理由の1つです。T-SQLで何を実行しているのか、SQL Serverで何をしているのかを正確に把握できます。結局のところ、明示的なコマンドを発行しました。GUIを使用する場合、実際のT-SQLは抽象化されます。この場合、ブロックされたオブジェクトエクスプローラーがデータベースをオフラインにしようとする試みを調べましたALTER DATABASE <YourDatabase> SET OFFLINE。ロールバックの試みはなかったため、無期限に待機していました。あなたのケースでは、そのデータベースがロックされているセッションをロールバックしたい場合は、ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATEロールバックが大丈夫であると最初に判断した場合に十分でしょう。



0

何もする必要はありません。SqLWB.exeタスクマネージャからプロセスを強制終了し、SQL Serverを開き、データベースを右クリックしてオフラインにします。それが機能しない場合は、セッションが終了した後、次のコマンドを入力します

ALTER DATABASE [Test4] SET OFFLINE WITH ROLLBACK IMMEDIATE

そしてオフライン。それは私のためにも働いたようにそれは動作します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.