4

プロセスを強制終了しないように見えるため、次を変更したいと思います-ユーザーを切断することになっていると思います(これは同じですか?)。特定のデータベースのすべてのプロセスを強制終了できるようにしたい - 以下を変更するにはどうすればよいですか:

create procedure [dbo].[sp_killusers](@database varchar(30))
as
----------------------------------------------------
-- * Created By David Wiseman, Updated 19/11/2006
-- * http://www.wisesoft.co.uk
-- * This procedure takes the name of a database as input
-- * and uses the kill statment to disconnect them from
-- * the database.
-- * PLEASE USE WITH CAUTION!!
-- * Usage:
-- * exec sp_killusers 'databasename'
----------------------------------------------------
set nocount on
declare @spid int
declare @killstatement nvarchar(10)

-- Declare a cursor to select the users connected to the specified database
declare c1 cursor for select request_session_id
                                from sys.dm_tran_locks
                                    where resource_type='DATABASE'
                                    AND DB_NAME(resource_database_id) = @database
open c1
fetch next from c1 into @spid
-- for each spid...
while @@FETCH_STATUS = 0
begin
      -- Don't kill the connection of the user executing this statement
      IF @@SPID <> @spid
      begin
            -- Construct dynamic sql to kill spid
            set @killstatement = 'KILL ' + cast(@spid as varchar(3))
            exec sp_executesql @killstatement
            -- Print killed spid
            print @spid
      end
      fetch next from c1 into @spid
end
-- Clean up
close c1
deallocate c1

アップデート

上記は機能しません。つまり、プロセスを強制終了しません。

プロセスを強制終了しません。アクティビティ モニターを見ると、まだプロセスが継続していることを示しており、クエリ ウィンドウでクエリがまだ機能していることがわかります。「kill 53」を実行すると、クエリ ウィンドウでクエリが停止し、プロセスがアクティビティ モニターから消えます。kill は機能しますが、この手順では機能しないのはなぜですか?

4

6 に答える 6

3

特定の DB でのすべてのアクティビティを停止しようとしているだけで、メンテナンスを行うことができますか?

その場合、次のことができます。

ALTER DATABASE myDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

これにより、DB にアクセスしている他のすべての SPID が強制終了され、DB がシングル ユーザー モードになります。次に、メンテナンス アクションを実行し、その後、次の操作を行います。

ALTER DATABASE myDB SET MULTI_USER;
于 2009-12-08T03:18:03.527 に答える
2

私はこのスクリプトに精通しています。はい、データベースを使用しているすべての SPID を強制終了します。正しいアクセス許可で実行する必要があります。すべてのユーザーが SPID を強制終了できるわけではありません。

また、DB への永続的な接続を試みて維持しようとするアプリケーションが存在する可能性があるため、SPID を強制終了した直後に再接続する可能性があります。

于 2009-11-27T12:10:15.157 に答える
0

これは、SQLServer 2000で機能します

DECLARE @DbName VARCHAR(100)
DECLARE @SPID INT
DECLARE @TranUOW UNIQUEIDENTIFIER
DECLARE @KillStmt NVARCHAR(100)

SET @DbName = 'MyDatabase'

-----------------------------------
-- Kill distributed transactions

DECLARE dist CURSOR FOR
    SELECT DISTINCT req_transactionUOW
        FROM master..syslockinfo
        WHERE db_name(rsc_dbid) = @DbName
              AND req_transactionUOW <> '00000000-0000-0000-0000-000000000000'

OPEN dist

FETCH NEXT FROM dist INTO @TranUOW

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @KillStmt = 'kill ''' + CAST(@TranUOW AS VARCHAR(50)) + ''''

    PRINT @KillStmt
    EXECUTE(@KillStmt)

    FETCH NEXT FROM dist INTO @TranUOW
END

CLOSE dist
DEALLOCATE dist

-----------------------------------
-- Kill user connections

DECLARE cur CURSOR FOR
    SELECT spid
        FROM master..sysprocesses
        WHERE db_name(dbid) = @DbName
              AND spid > 50

OPEN cur

FETCH NEXT FROM cur INTO @SPID

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @KillStmt = 'kill ' + CAST(@SPID AS VARCHAR(10))

    PRINT @KillStmt
    EXECUTE(@KillStmt)

    FETCH NEXT FROM cur INTO @SPID
END

CLOSE cur
DEALLOCATE cur
于 2009-12-08T07:20:10.717 に答える
0

これらのどれにも当てはまらない可能性は十分にありますが、念のために、数年前にこのような作業を行ったときに遭遇した奇妙な状況をいくつか紹介します (すべて SQL 2005)。

  • 自分の接続を切断することはできません。
  • 私が使用したコードでは、51 未満の spid を決してkill しようとしないようにしました。
  • 接続がトランザクションを処理している場合、強制終了する前にそのトランザクションをロールバックする必要があります。巨大なトランザクションは、ロールバックにかなりの時間がかかる場合があります。
  • 接続プーリングに注意してください。彼らはアンデッドのようなものです。殺せばすぐに戻ってきます。多くの場合、1 秒もかかりません。

このプロセスの実行中に SQL プロファイラーを実行し、ログインとログアウトを追跡すると、特に接続プールの問題が明らかになる場合があります。

于 2009-12-07T16:22:46.663 に答える
0

プロシージャの実行時に実際に発生することのデバッグ/出力を試しましたか? たとえば、@killstatement を nvarchar(max) として宣言するように変更し、次のような詳細な出力を含めて、結果を投稿できますか? 基本的に、begin/end ブロック内のすべてを次のようなものに置き換えます。

-- Construct dynamic sql to kill spid
select  @killstatement = N'
            select  *
            from    sys.dm_exec_sessions s
            join    sys.dm_exec_connections c
            on      s.session_id = c.session_id
            where   c.session_id = @spid;

            kill ' + cast(@spid as varchar(3)) + ';

            select  *
            from    sys.dm_exec_sessions s
            join    sys.dm_exec_connections c
            on      s.session_id = c.session_id
            where   c.session_id = @spid;           
        ';
-- Print & Exec
print @killstatement;
exec sp_executesql @killstatement, N'@spid smallint', @spid;
print @spid;

プロシージャ コード内で動作する場合と、接続内で明示的に実行する場合とでは、何かが異なる動作をする必要がある理由はありません。適切な権限があり、有効な spid を強制終了していると仮定します。上記のようなデバッグの結果を投稿できれば (試したことがあるかもしれません)、問題がどこにあるかを把握するのに役立ちます。使用しているカーソル宣言の結果のデバッグ出力を含めて、強制終了しようとしているセッションを実際に取得していることを確認することもできます。つまり、カーソル宣言で使用しているのと同じ選択を含めるだけで、次のような結果セット:

declare c1 cursor for select request_session_id
                                from sys.dm_tran_locks
                                    where resource_type='DATABASE'
                                    AND DB_NAME(resource_database_id) = @database

-- Debug output - sessions we should try and kill...
select  request_session_id
from    sys.dm_tran_locks
where   resource_type='DATABASE'
AND     DB_NAME(resource_database_id) = @database;

結果を投稿していただければ、私たちに何かが続くことを願っています。

于 2009-12-03T16:18:53.473 に答える
0

sp_exec の代わりに exec を使用してみてください (違いはありません)。

SET @killstatement = 'KILL ' + cast(@spid as varchar(3)) 
EXEC (@killstatement)
于 2009-11-30T07:18:55.347 に答える