[SQL] 스크립트가 데이터베이스에 모든 연결을 죽일 (더 RESTRICTED_USER ROLLBACK 이상)
SQL스크립트가 데이터베이스에 모든 연결을 죽일 (더 RESTRICTED_USER ROLLBACK 이상)
나는 (A 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에있는 유일한 하나입니다.)
연결된 사용자의 내 데이터베이스에 관계없이 삭제할 수있는 스크립트가 있습니까?
해결법
-
==============================
1.업데이트
업데이트
위의 MS SQL 서버 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);
2008 MS SQL 서버 2000, 2005의 경우
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);
-
==============================
2.
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
-
==============================
3.당신은 SSMS 다음을 수행하여 제공하는 스크립트를 얻을 수 있습니다 :
당신은 SSMS 다음을 수행하여 제공하는 스크립트를 얻을 수 있습니다 :
스크립트는 다음과 같이 표시됩니다
USE [master] GO ALTER DATABASE [YourDatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE GO USE [master] GO DROP DATABASE [YourDatabaseName] GO
-
==============================
4.작은 알려진 다음 GO SQL 문은 이전 명령을 반복 할 횟수에 대한 정수를 취할 수 있습니다.
작은 알려진 다음 GO SQL 문은 이전 명령을 반복 할 횟수에 대한 정수를 취할 수 있습니다.
당신이 경우에 따라서 :
ALTER DATABASE [DATABASENAME] SET SINGLE_USER GO
그때:
USE [DATABASENAME] GO 2000
이것은 다른 모든 연결에 사용 명령 2000 회, 힘의 교착 상태를 반복하고, 단일 연결의 소유권을 취할 것입니다. (당신이 원하는대로 할 쿼리 창 단독 액세스를 부여.)
-
==============================
5.내 경험에, SINGLE_USER를 사용하는 시간의 대부분은, 그러나, 하나는주의해야하는 데 도움이 : 나는 내가 SINGLE_USER 명령하고 종료 시간을 시작 시간 사이에있는 경험이 풍부한 경우가 ... 분명히 다른 '사용자'가 먹은 SINGLE_USER 액세스하지 나. 그렇게되면, 데이터베이스의 뒷면에 접근려고 힘든 작업에있어 (내 경우를, 내가 한 전에 SINGLE_USER 액세스 잡고있어 SQL 데이터베이스와 소프트웨어를 실행하는 특정 서비스이었다). 내가 생각하는 가장 신뢰할 수있는 방법이 (그것을 위해 보증 할 수 있지만, 내가 올 일에 테스트 할 것입니다), 실제로한다 : - (존재하는 경우) 액세스를 방해 할 수 있습니다 스톱 서비스 - 모든 연결을 닫습니다 위의 '죽'스크립트를 사용하여 - 직후 그 SINGLE_USER에 대한 데이터베이스를 설정 - 다음 복원 할
내 경험에, SINGLE_USER를 사용하는 시간의 대부분은, 그러나, 하나는주의해야하는 데 도움이 : 나는 내가 SINGLE_USER 명령하고 종료 시간을 시작 시간 사이에있는 경험이 풍부한 경우가 ... 분명히 다른 '사용자'가 먹은 SINGLE_USER 액세스하지 나. 그렇게되면, 데이터베이스의 뒷면에 접근려고 힘든 작업에있어 (내 경우를, 내가 한 전에 SINGLE_USER 액세스 잡고있어 SQL 데이터베이스와 소프트웨어를 실행하는 특정 서비스이었다). 내가 생각하는 가장 신뢰할 수있는 방법이 (그것을 위해 보증 할 수 있지만, 내가 올 일에 테스트 할 것입니다), 실제로한다 : - (존재하는 경우) 액세스를 방해 할 수 있습니다 스톱 서비스 - 모든 연결을 닫습니다 위의 '죽'스크립트를 사용하여 - 직후 그 SINGLE_USER에 대한 데이터베이스를 설정 - 다음 복원 할
-
==============================
6.마태 복음의 굉장히 효율적인 스크립트는 사용되지 않는 sysprocesses 시스템 테이블을 대체하는 dm_exec_sessions DMV를 사용하도록 업데이트 :
마태 복음의 굉장히 효율적인 스크립트는 사용되지 않는 sysprocesses 시스템 테이블을 대체하는 dm_exec_sessions DMV를 사용하도록 업데이트 :
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;
WHILE 루프를 (당신이 실행에 따라 다른 작업을 처리 할 경우)를 사용하여 대체 :
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;
-
==============================
7.허용 대답은 데이터베이스에 연결된 데이터베이스가 아닌 다른 데이터베이스에 테이블을 포함하는 쿼리를 실행하는 연결에 의해 고정 될 수는 고려하지 않는다는 단점이있다.
허용 대답은 데이터베이스에 연결된 데이터베이스가 아닌 다른 데이터베이스에 테이블을 포함하는 쿼리를 실행하는 연결에 의해 고정 될 수는 고려하지 않는다는 단점이있다.
서버 인스턴스가 하나 이상의 데이터베이스와 쿼리를 직접 또는 간접적으로 (동의어를 통해 예를 들어) 사용 테이블 하나 이상의 데이터베이스 등이 경우에 해당 될 수 있습니다
그래서 저는 가끔 죽일 연결을 찾을 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);
-
==============================
8.당신은 프로세스 종료시 예외주의해야한다. 이 스크립트를 사용할 수 있도록 :
당신은 프로세스 종료시 예외주의해야한다. 이 스크립트를 사용할 수 있도록 :
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)
-
==============================
9.@AlexK은 훌륭한 대답을 썼다. 난 그냥 내 두 센트를 추가 할. 아래의 코드가 완전히 AlexK의 대답 @ 기반으로, 차이는 마지막 일괄 처리가 실행 된 이후에는 사용자와 시간을 지정할 수 있다는 것입니다 (참고 대신 master..sysprocess의 코드 사용의 바로 sys.dm_exec_sessions) :
@AlexK은 훌륭한 대답을 썼다. 난 그냥 내 두 센트를 추가 할. 아래의 코드가 완전히 AlexK의 대답 @ 기반으로, 차이는 마지막 일괄 처리가 실행 된 이후에는 사용자와 시간을 지정할 수 있다는 것입니다 (참고 대신 master..sysprocess의 코드 사용의 바로 sys.dm_exec_sessions) :
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)
이 예에서 마지막 배치는 1 시간 이상 전에 실행 된 사용자 usrDBTest의 프로세스는 삭제됩니다.
-
==============================
10.당신은 그렇게 커서를 사용할 수 있습니다 :
당신은 그렇게 커서를 사용할 수 있습니다 :
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
-
==============================
11.
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 */
-
==============================
12.나는 아래의 간단한 코드로 성공적으로 테스트 한
나는 아래의 간단한 코드로 성공적으로 테스트 한
USE [master] GO ALTER DATABASE [YourDatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE GO
from https://stackoverflow.com/questions/7197574/script-to-kill-all-connections-to-a-database-more-than-restricted-user-rollback by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 오라클 키워드 "으로 파티션" (0) | 2020.05.06 |
---|---|
[SQL] SQL Server의 '테이블을 설명'에 해당 무엇입니까? (0) | 2020.05.06 |
[SQL] 오라클 업데이트 쿼리에 참여하여 (0) | 2020.05.06 |
[SQL] 와 업데이트는 오라클에서 쿼리 가입 (0) | 2020.05.06 |
[SQL] 특별한 제외하고, 다른 모든 후에는 null 값을 정렬 (0) | 2020.05.06 |