source

데이터베이스에 대한 모든 연결을 끊는 스크립트(RESTRICTED_USER Rollback 이상)

ittop 2023. 4. 17. 22:27
반응형

데이터베이스에 대한 모든 연결을 끊는 스크립트(RESTRICTED_USER Rollback 이상)

Visual Studio Database 프로젝트에서 (TFS 자동 빌드를 통해) 자주 다시 배포하는 개발 데이터베이스가 있습니다.

빌드를 실행하면 다음과 같은 오류가 발생할 수 있습니다.

ALTER DATABASE failed because a lock could not be placed on database 'MyDB'. Try again later.  
ALTER DATABASE statement failed.  
Cannot drop database "MyDB" because it is currently in use.  

이거 해봤어요.

ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE

대부분의 가지고 있을 dbo을 이용하다

으로 실행할 수 .SP_WHO이번삭제하려고 하는 것은 DB상의 접속뿐입니다만)

접속자에 관계없이 데이터베이스를 삭제할 수 있는 스크립트가 있습니까?

갱신필

MS SQL Server 2012 이상용

USE [master];

DECLARE @kill varchar(8000) = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), session_id) + ';'  
FROM sys.dm_exec_sessions
WHERE database_id  = db_id('MyDB')

EXEC(@kill);

MS SQL Server 2000, 2005, 2008의 경우

USE master;

DECLARE @kill varchar(8000); SET @kill = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), spid) + ';'  
FROM master..sysprocesses  
WHERE dbid = db_id('MyDB')

EXEC(@kill); 
USE master
GO
ALTER DATABASE database_name
SET OFFLINE WITH ROLLBACK IMMEDIATE
GO

참고 자료: http://msdn.microsoft.com/en-us/library/bb522682%28v=sql.105%29.aspx

SSMS가 제공하는 스크립트를 입수하려면 , 다음의 순서에 따릅니다.

  1. SSMS에서 데이터베이스를 마우스 오른쪽 버튼으로 클릭하고 delete를 선택합니다.
  2. 대화상자에서 "기존 연결 닫기" 확인란을 선택합니다.
  3. 대화상자 상단에 있는 [스크립트]버튼을 클릭합니다.

스크립트는 다음과 같습니다.

USE [master]
GO
ALTER DATABASE [YourDatabaseName] SET  SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
USE [master]
GO
DROP DATABASE [YourDatabaseName]
GO

거의 알려지지 않음: GO sql 문은 이전 명령을 반복하는 횟수만큼 정수를 사용할 수 있습니다.

따라서 다음과 같은 경우:

ALTER DATABASE [DATABASENAME] SET SINGLE_USER
GO

그 후, 다음과 같이 입력합니다.

USE [DATABASENAME]
GO 2000

그러면 USE 명령어가 2000회 반복되고 다른 모든 연결에서 데드록이 강제로 실행되며 단일 연결의 소유권을 획득합니다(쿼리 창에만 원하는 액세스 권한을 부여합니다).

으로는 SINGLE_USER를 해야 합니다.SINGLE_USER는 SINGLE_USER입니다.SINGLE_USER는 내.내가 아닌 다른 '사용자'가 SINGLE_USER 접근권을 가지고 있었던 것 같습니다.이 경우 데이터베이스에 대한 접근을 되돌리려면 어려운 작업이 필요합니다(이 경우 SQL 데이터베이스를 가진 소프트웨어에서 실행 중인 특정 서비스가 먼저 SINGLE_USER 액세스를 확보했습니다).가장 신뢰할 수 있는 방법(보증할 수는 없지만 앞으로 테스트해 보겠습니다)은 실제로 다음과 같습니다.
수 있는 경우 - "서비스 중지"
- 위의 'kill' 스크립트를 사용하여 모든 연결을 닫습니다.
- 그 직후에 데이터베이스를 single_user로 설정합니다.
- restore를 실행합니다.

Matthew의 매우 효율적인 스크립트는 dm_exec_sessions DMV를 사용하도록 업데이트되어 사용되지 않는 syspprocesses 시스템 테이블을 대체합니다.

USE [master];
GO

DECLARE @Kill VARCHAR(8000) = '';

SELECT
    @Kill = @Kill + 'kill ' + CONVERT(VARCHAR(5), session_id) + ';'
FROM
    sys.dm_exec_sessions
WHERE
    database_id = DB_ID('<YourDB>');

EXEC sys.sp_executesql @Kill;

WHY 루프를 사용하는 대체 방법(실행별로 다른 작업을 처리하는 경우):

USE [master];
GO

DECLARE @DatabaseID SMALLINT = DB_ID(N'<YourDB>');    
DECLARE @SQL NVARCHAR(10);

WHILE EXISTS ( SELECT
                1
               FROM
                sys.dm_exec_sessions
               WHERE
                database_id = @DatabaseID )    
    BEGIN;
        SET @SQL = (
                    SELECT TOP 1
                        N'kill ' + CAST(session_id AS NVARCHAR(5)) + ';'
                    FROM
                        sys.dm_exec_sessions
                    WHERE
                        database_id = @DatabaseID
                   );
        EXEC sys.sp_executesql @SQL;
    END;

허용된 답변에는 연결된 데이터베이스 이외의 데이터베이스에 있는 테이블을 포함하는 쿼리를 실행하는 연결에 의해 데이터베이스가 잠길 수 있다는 점이 고려되지 않는다는 단점이 있습니다.

이는 서버 인스턴스에 여러 데이터베이스가 있고 쿼리가 여러 데이터베이스의 테이블을 직간접적으로(예를 들어 동의어를 통해) 사용하는 경우에 해당됩니다.

따라서 syslockinfo를 사용하여 죽일 연결을 찾는 것이 더 나을 수 있습니다.

따라서 AlexK가 승인한 답변을 다음과 같이 변형하여 사용할 것을 제안합니다.

USE [master];

DECLARE @kill varchar(8000) = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), req_spid) + ';'  
FROM master.dbo.syslockinfo
WHERE rsc_type = 2
AND rsc_dbid  = db_id('MyDB')

EXEC(@kill);

살인 과정에서는 예외에 주의해야 합니다.따라서 다음 스크립트를 사용할 수 있습니다.

USE master;
GO
 DECLARE @kill varchar(max) = '';
 SELECT @kill = @kill + 'BEGIN TRY KILL ' + CONVERT(varchar(5), spid) + ';' + ' END TRY BEGIN CATCH END CATCH ;' FROM master..sysprocesses 
EXEC (@kill)

@AlexK는 훌륭한 답변을 썼다.나는 단지 내 의견을 덧붙이고 싶다.아래 코드는 전적으로 @AlexK의 답변에 기초하고 있습니다.차이점은 사용자와 마지막 배치가 실행된 이후의 시간을 지정할 수 있다는 것입니다(코드는 마스터 대신 sys.dm_exec_display를 사용합니다).syspprocess) :

DECLARE @kill varchar(8000);
set @kill =''
select @kill = @kill + 'kill ' +  CONVERT(varchar(5), session_id) + ';' from sys.dm_exec_sessions 
where login_name = 'usrDBTest'
and datediff(hh,login_time,getdate()) > 1
--and session_id in (311,266)    
exec(@kill)

이 예에서는 사용자 usrDB 프로세스만마지막 배지가 1시간 이상 전에 실행된 테스트는 중지됩니다.

다음과 같이 커서를 사용할 수 있습니다.

USE master
GO

DECLARE @SQL AS VARCHAR(255)
DECLARE @SPID AS SMALLINT
DECLARE @Database AS VARCHAR(500)
SET @Database = 'AdventureWorks2016CTP3'

DECLARE Murderer CURSOR FOR
SELECT spid FROM sys.sysprocesses WHERE DB_NAME(dbid) = @Database

OPEN Murderer

FETCH NEXT FROM Murderer INTO @SPID
WHILE @@FETCH_STATUS = 0

    BEGIN
    SET @SQL = 'Kill ' + CAST(@SPID AS VARCHAR(10)) + ';'
    EXEC (@SQL)
    PRINT  ' Process ' + CAST(@SPID AS VARCHAR(10)) +' has been killed'
    FETCH NEXT FROM Murderer INTO @SPID
    END 

CLOSE Murderer
DEALLOCATE Murderer

블로그에 써놨어요.http://www.pigeonsql.com/single-post/2016/12/13/Kill-all-connections-on-DB-by-Cursor

SELECT
    spid,
    sp.[status],
    loginame [Login],
    hostname, 
    blocked BlkBy,
    sd.name DBName, 
    cmd Command,
    cpu CPUTime,
    memusage Memory,
    physical_io DiskIO,
    lastwaittype LastWaitType,
    [program_name] ProgramName,
    last_batch LastBatch,
    login_time LoginTime,
    'kill ' + CAST(spid as varchar(10)) as 'Kill Command'
FROM master.dbo.sysprocesses sp 
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
WHERE sd.name NOT IN ('master', 'model', 'msdb') 
--AND sd.name = 'db_name' 
--AND hostname like 'hostname1%' 
--AND loginame like 'username1%'
ORDER BY spid

/* If a service connects continously. You can automatically execute kill process then run your script:
DECLARE @sqlcommand nvarchar (500)
SELECT @sqlcommand = 'kill ' + CAST(spid as varchar(10))
FROM master.dbo.sysprocesses sp 
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
WHERE sd.name NOT IN ('master', 'model', 'msdb') 
--AND sd.name = 'db_name' 
--AND hostname like 'hostname1%' 
--AND loginame like 'username1%'
--SELECT @sqlcommand
EXEC sp_executesql @sqlcommand
*/
USE MASTER
GO
 
DECLARE @Spid INT
DECLARE @ExecSQL VARCHAR(255)
 
DECLARE KillCursor CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT  DISTINCT SPID
FROM    MASTER..SysProcesses
WHERE   DBID = DB_ID('dbname')
 
OPEN    KillCursor
 
-- Grab the first SPID
FETCH   NEXT
FROM    KillCursor
INTO    @Spid
 
WHILE   @@FETCH_STATUS = 0
    BEGIN
        SET     @ExecSQL = 'KILL ' + CAST(@Spid AS VARCHAR(50))
 
        EXEC    (@ExecSQL)
 
        -- Pull the next SPID
        FETCH   NEXT 
        FROM    KillCursor 
        INTO    @Spid  
    END
 
CLOSE   KillCursor
 
DEALLOCATE  KillCursor

데이터베이스만 삭제/삭제하려면 기본적으로 설정되지 않은 "기존 연결 닫기" 옵션을 선택할 수 있습니다.

  1. [ Database catalog - ]-> 옵션을 오른쪽 클릭합니다.
  2. [ Delete - > ]체크박스를 켜겠습니다
  3. 네 알겠습니다

여기에 이미지 설명 입력

아래의 간단한 코드로 테스트에 성공했습니다.

USE [master]
GO
ALTER DATABASE [YourDatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

언급URL : https://stackoverflow.com/questions/7197574/script-to-kill-all-connections-to-a-database-more-than-restricted-user-rollback

반응형