SQL Server 2005データベースへの現在の接続をすべて強制終了するにはどうすればよいですか?


288

データベースの名前を変更したいのですが、データベースで「排他ロックを取得できませんでした」というエラーが発生し続けます。これは、いくつかの接続がまだアクティブであることを意味します。

名前を変更できるように、データベースへのすべての接続を強制終了するにはどうすればよいですか?

回答:


378

Adamが提案したアプローチが機能しない理由は、アクティブな接続をループしている間、新しい接続を確立でき、それらを逃してしまうためです。代わりに、この欠点のない次のアプローチを使用できます。

-- set your current connection to use master otherwise you might get an error

use master
ALTER DATABASE YourDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE 

--do you stuff here 

ALTER DATABASE YourDatabase SET MULTI_USER

1
SQL Server 2008では機能しないようです。次のエラーが表示されます。コンソール:メッセージ102、レベル15、状態1、行4 '-'付近の構文が正しくありません。メッセージ319、レベル15、状態1、行4キーワード「with」の近くの不正な構文。このステートメントが共通テーブル式、xmlnamespaces句、または変更追跡コンテキスト句の場合、前のステートメントはセミコロンで終了する必要があります。メッセージ102、レベル15、状態1、行4「IMMEDIATE」付近の構文が正しくありません。コマンド:ALTER DATABASE ASMR-wdanda SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Wagner da Silva

私はこれを2008年に問題なく実行しただけです。ALTERDATABASE aspnetdb SET SINGLE_USER WITH ROLLBACK IMMEDIATE select GETDATE()ALTER DATABASE aspnetdb SET MULTI_USERコメントアウトされたコードの代わりに何がありますか?
SQLMenace 2010

SQL Server 2008とSQL Expressインスタンスで私のために働いた。
Tim Murphy、

19
@Wagnerデータベースの名前に「-」が含まれる場合は、括弧で囲む必要があります。ALTERDATABASE [foo-bar] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Ben Challenor

14
注意-Amazon RDSでホストされているSQL Serverでこれを試さないでください。DBをMULTI_USERモードにリセットすることはできません。これを行う前に、DBA資格情報の別のセットがあることを確認してください。以前のスナップショットの1つに戻すことでこれを修正しました。一部のデータを失った。幸い、データは重要ではありませんでした。
RuntimeException

110

これを実行するためのスクリプト。「DB_NAME」をデータベースに置き換えて、以下へのすべての接続を強制終了します。

USE master
GO

SET NOCOUNT ON
DECLARE @DBName varchar(50)
DECLARE @spidstr varchar(8000)
DECLARE @ConnKilled smallint
SET @ConnKilled=0
SET @spidstr = ''

Set @DBName = 'DB_NAME'
IF db_id(@DBName) < 4
BEGIN
PRINT 'Connections to system databases cannot be killed'
RETURN
END
SELECT @spidstr=coalesce(@spidstr,',' )+'kill '+convert(varchar, spid)+ '; '
FROM master..sysprocesses WHERE dbid=db_id(@DBName)

IF LEN(@spidstr) > 0
BEGIN
EXEC(@spidstr)
SELECT @ConnKilled = COUNT(1)
FROM master..sysprocesses WHERE dbid=db_id(@DBName)
END

1
これは私にとってはうまくいきましand spid <> @@SPIDた。SELECT @sKillConnection現在の接続を強制終了しようとしないようにステートメントに追加しました。これにより、エラーメッセージが生成されます。
ルイス・ペレス

強制終了できるのはユーザープロセスだけです...デッドロックのままで、デッドロックが原因でmulti_userモードを復元できません。
rainabba 2013

mateuscb-mssql 10.00で機能しない唯一の方法は、[]を必要とするデータベース名があり、それらを使用しない場合です。ALTER DATABASE [YourDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATEは、10、10.5、11、12で機能します
Jeremy

命の恩人。トップアンサーでなければなりません。
gls123 2017

55

それを殺し、火で殺す:

USE master
go

DECLARE @dbname sysname
SET @dbname = 'yourdbname'

DECLARE @spid int
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname)
WHILE @spid IS NOT NULL
BEGIN
EXECUTE ('KILL ' + @spid)
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname) AND spid > @spid
END

27

SQL Management Studio Expressの使用:

オブジェクトエクスプローラーのツリーで、[管理]の下の[アクティビティモニター]にドリルダウンします(見つからない場合は、データベースサーバーを右クリックして[アクティビティモニター]を選択します)。アクティビティモニターを開くと、すべてのプロセス情報を表示できます。関心のあるデータベースのロックを見つけて、それらのロックを強制終了できるはずです。これにより、接続も強制終了されます。

その後、名前を変更できるはずです。


この[アクティビティモニター]項目が[管理]に表示されません...繰り返しますが、SQL 2008を使用しているためと思われますか?
ワーグナー

14
DBではなくSERVERを右クリックすると、「アクティビティモンティオール」が見つかりました。次に、「プロセス」タブを選択し、データベースでフィルタリングできます。
alirobe 2010年

停止したプロセスを1つずつ強制終了する必要があるようですが、ローカルログインやデータベースサーバー全体の停止を必要としない簡単な方法です。
アルバロ・ゴンサレス

24

私はいつも使ってきました:


ALTER DATABASE DB_NAME SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
GO 
SP_RENAMEDB 'DB_NAME','DB_NAME_NEW'
Go 
ALTER DATABASE DB_NAME_NEW  SET MULTI_USER -- set back to multi user 
GO 


14

オフラインにすると時間がかかり、時々私はいくつかの問題を経験します。

私の意見では最も堅実な方法:

切り離す 右クリック >タスク->デタッチ...「ドロップ接続」を確認します

再接続 右クリックデータベース->添付....追加...- >データベースを選択し、[添付]列を目的のデータベース名に変更します。OK


いいね。確かにGUIからそれを行う最も速い方法。
Whelkaholism 2013

それは魅力のように機能します!簡単な方法が良い方法です。ありがとう。
2016

6
Select 'Kill '+ CAST(p.spid AS VARCHAR)KillCommand into #temp
from master.dbo.sysprocesses p (nolock)
join master..sysdatabases d (nolock) on p.dbid = d.dbid
Where d.[name] = 'your db name'

Declare @query nvarchar(max)
--Select * from #temp
Select @query =STUFF((                              
            select '  ' + KillCommand from #temp
            FOR XML PATH('')),1,1,'') 
Execute sp_executesql @query 
Drop table #temp

'master'データベースを使用してこのクエリを実行すると、データベースからのアクティブな接続がすべて強制終了されます。


1
それは本当に機能します:)しかし、このスクリプトの実行部分をコメントアウトしておいて、代わりにprint @queryを置くことをお勧めします。これは、本番サーバーで誤って実行しないようにするためです。
マルチェロミオレッリ2014

5

通常、データベースを復元しようとすると、このエラーが発生します。通常、Management Studioのツリーの一番上に移動し、データベースサーバーを右クリックして再起動します(開発マシン上にあるため、これは本番環境では理想的ではない可能性があります) )。これはすべてのデータベース接続を閉じます。


おかげで、これはうまくいきました(ALTER DATABASE ... SET SINGLE_USER他の回答のコマンドは同じ「排他ロックを取得できませんでした」エラーを返しました)。
ティニスター

4

オブジェクトエクスプローラーのMS SQL Server Management Studioで、データベースを右クリックします。次のコンテキストメニューで、[タスク]-> [オフラインにする]を選択します。


4
アクティブな接続がある場合、これを行うことはできません。
10

4

もう1つの「火事でそれを殺す」アプローチは、MSSQLSERVERサービスを再起動することです。コマンドラインから何かをするのが好きです。これをCMDに正確に貼り付けると、次のようになります。NETSTOP MSSQLSERVER&NET START MSSQLSERVER

または、「services.msc」を開き、「SQL Server(MSSQLSERVER)」を見つけて右クリックし、「再起動」を選択します。

これにより、そのインスタンスで実行されているすべてのデータベースへのすべての接続が「確実に」強制終了されます。

(私はこれを変更してサーバー/データベースの構成を変更して戻す多くのアプローチよりも優れています)


「非推奨」とはどういう意味ですか?そのサーバーへの接続(つまり、デバッグ環境やステージング環境など、または一時的なダウンタイムが発生する本番サーバー)に関心がない場合は、これが最も簡単な方法です。本番環境の場合-サービスを再起動するだけでよい場合は、設定をいじくりまわしたくない。あなたならどうしますか?
aikeru

1
私は自分のターゲットDBのみに影響するはずのものに行きます。ターゲットサーバー上のすべてのDBを強制終了するというアプローチはそれほど賢くありません。しかし、正直に言うと、ステージング環境では、これはおそらくあなたが言った最も簡単な方法です。
Mohammed Swillam 2013

4

MS SQL Server Management Studio 2008でこの種のことを確実に行う方法は次のとおりです(他のバージョンでも機能する場合があります)。

  1. オブジェクトエクスプローラーツリーで、ルートデータベースサーバー(緑の矢印)を右クリックし、[アクティビティモニター]をクリックします。
  2. アクティビティモニターで[プロセス]タブを開き、[データベース]ドロップダウンメニューを選択して、目的のデータベースでフィルターします。
  3. オブジェクトエクスプローラーでDBを右クリックし、[タスク]-> [オフラインにする]タスクを開始します。あなたがいる間、これをバックグラウンドで実行したままにします...
  4. できる限り安全にシャットダウンします。
  5. プロセスタブから残りのすべてのプロセスを強制終了します。
  6. DBをオンラインに戻します。
  7. DBの名前を変更します。
  8. サービスをオンラインに戻し、新しいDBを指すようにします。

3

このシナリオで私にとって有効なオプションは次のとおりです。

  1. 問題のデータベースで「デタッチ」操作を開始します。これにより、DBでのアクションを防止するアクティブな接続を表示するウィンドウ(SQL 2005)が開きます。
  2. アクティブな接続を強制終了し、切り離し操作をキャンセルします。
  3. これで、データベースを復元できるようになります。

SQL 2008 Management Studioでは、何らかの理由で、[デタッチ]画面からアクティブな接続にアクセスできなくなります。それは2005年にうまく機能し、2008年にアップグレードするまで、これは私がいつも行っていた方法です。今では、接続を閉じるように指示するが、接続の詳細を開いて各接続を強制終了することを許可しない愚かなメッセージだけが表示されます。 。
ジム


2

データベース名を右クリックし、[プロパティ]をクリックしてプロパティウィンドウを取得します。[オプション]タブを開き、[アクセス制限]プロパティをマルチユーザーからシングルユーザーに変更します。OKボタンを押すと、開いているすべての接続を閉じるように求められます。[はい]を選択すると、データベースの名前を変更するように設定されます。


2

これらは私にとっては機能しませんでした(SQL2008 Enterprise)。また、DBに接続されている実行中のプロセスやユーザーも確認できませんでした。サーバーを再起動(Management StudioでSQL Serverを右クリックして[再起動]を選択)すると、DBを復元できました。



0

sp_whoを使用して、データベース内のすべてのプロセスのリストを取得します。強制終了するプロセスを確認する必要がある場合があるため、これはより良い方法です。

declare @proc table(
    SPID bigint,
    Status nvarchar(255),
    Login nvarchar(255),
    HostName nvarchar(255),
    BlkBy nvarchar(255),
    DBName nvarchar(255),
    Command nvarchar(MAX),
    CPUTime bigint,
    DiskIO bigint,
    LastBatch nvarchar(255),
    ProgramName nvarchar(255),
    SPID2 bigint,
    REQUESTID bigint
)

insert into @proc
exec sp_who2

select  *, KillCommand = concat('kill ', SPID, ';')
from    @proc

結果
KillCommand列のコマンドを使用して、必要なプロセスを強制終了できます。

SPID    KillCommand
26      kill 26;
27      kill 27;
28      kill 28;

-1

SP_Whoコマンドを使用して、データベースを使用するすべてのプロセスを強制終了してから、データベースの名前を変更できます。

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