SQL Server <dbname> 데이터베이스가 현재 사용 중이기 때문에 세션을 삭제할 수 없지만 세션이 표시되지 않습니다


72

데이터베이스를 삭제하려고하면 "현재 사용중인 데이터베이스"dbname "을 삭제할 수 없습니다"라는 오류가 발생합니다. 그러나을 실행 sp_who2하면이 데이터베이스에 연결된 세션이 없습니다. 또한 데이터베이스를로 설정했습니다 single_user mode with rollback immediate.

왜 이런 일이 발생합니까?

답변:


20

제거하려는 DB의 데이터베이스 스냅 샷과 같은 종속성이 없는지 확인하십시오. 그러나 오류 메시지는 다르게 보입니다. 데이터베이스에 연결되어있는 숨겨진 프로세스가 없습니까? 데이터베이스를 다른 이름으로 바꾼 후 즉시 모든 세션을 종료하는 스크립트를 실행하여 데이터베이스를 삭제하는 것이 좋습니다.

이 선택을 기반으로 커서를 만듭니다.

  select  d.name , convert (smallint, req_spid) As spid
      from master.dbo.syslockinfo l, 
           master.dbo.spt_values v,
           master.dbo.spt_values x, 
           master.dbo.spt_values u, 
           master.dbo.sysdatabases d
      where   l.rsc_type = v.number 
      and v.type = 'LR' 
      and l.req_status = x.number 
      and x.type = 'LS' 
      and l.req_mode + 1 = u.number
      and u.type = 'L' 
      and l.rsc_dbid = d.dbid 
      and rsc_dbid = (select top 1 dbid from 
                      master..sysdatabases 
                      where name like 'my_db')

커서 내부의 문제 :

SET @kill_process =  'KILL ' + @spid      
            EXEC master.dbo.sp_executesql @kill_process
                   PRINT 'killed spid : '+ @spid

커서가 닫히고 할당이 해제 된 후 :

sp_dboption 'my_db', 'single user', 'TRUE'

go

sp_renamedb 'my_db', 'my_db_old'

go

DROP DATABASE MY_DB_OLD 

코드 주셔서 감사합니다-작동 할 수 있습니다. 내가 이해하지 못하는 것은 "숨겨진"세션이란 무엇입니까? sp_who와 다른 메타 데이터 (DMV)가 모든 세션을 보여줄 것이라고 생각했을 것입니다 .
tuseau

예, 일반적으로 sp_who를 통해 모든 활성 / 비활성을 보거나 master db에서 sysprocesses 테이블을 쿼리 할 수 ​​있습니다. 숨겨져 서 응용 프로그램 서비스에서 다시 연결되는 프로세스를 의미했습니다. 건배.
yrushka

1
(1) 이전 스타일 조인 (2) 이전 버전과의 호환성보기 (3) 단일 ALTER가 sp_dboption과 같은 더 이상 사용되지 않는 프로 시저를 수행 할 때 많은 KILL 명령을 실행하는 커서 및 동적 SQL.
Aaron Bertrand

1
불행히도 나는 이것이 질문에 대답하지 않는다고 생각한다-질문자는 왜 이것이 일어나고 있는지, 어떻게 해결해야하는지 묻고있다. 제공된 답변은 효과가 있지만 데이터베이스를 삭제하지 못하게하는 것이 무엇인지 여전히 모르겠습니다. @AaronBertrand는 "하나의 개체 탐색기가 범인 일 수도 있습니다"라고 언급했지만 실제로 데이터베이스 중 하나의 이유가되었지만 개체 탐색기라는 것을 어떻게 알 수 있습니까?
LearnByReading

이것은 나에게 "KILL을 사용하여 자신의 프로세스를 죽일 수 없습니다"라는 오류를 발생시킵니다.
nuander

80

다른 데이터베이스에 연결된 세션에는 데이터베이스에 영향을주는 열린 트랜잭션이있을 수 있습니다. sp_who2는 하나의 데이터베이스 만 표시합니다. SSMS에서 개체 탐색기 또는 개체 탐색기 세부 정보를 여는 것처럼 간단 할 수도 있습니다. sp_who2에는 데이터베이스가 하나만 표시됩니다.

책임있는 세션 을 찾으려고 노력하지 마십시오 . 하나의 문장으로 모두를 죽이십시오 (그리고 다른 쿼리 창, 객체 탐색기 등이 연결된 SSMS 사본이 아닌지 확인하십시오).

USE master;
GO
ALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO

이제 UI를 삭제하지 않고 DDL을 사용하여 삭제할 수 있습니다.

DROP DATABASE dbname;

1
귀하의 답변에 감사드립니다. 그러나이 솔루션을 사용하는 데 어려움을 겪고 있습니다.이 오류로 인해 일부 데이터베이스를 삭제할 수없는 이유는 무엇입니까? 1 년 동안 손대지 않은 일부 데이터베이스가 있으며 해당 데이터베이스에 연결된 프로세스 또는 확장 가능한 트랜잭션이 없습니다. 잠재적 인 서비스 나 트랜잭션 또는 이러한 데이터베이스에 연결된 것을 찾는 데 도움이되는 힌트를 주실 수 있습니까?
LearnByReading

1
사실 내가했던 일은이었다 USE master다음, DROP DATABASE dbname. 분명히 필요한 것은 다른 것을 "사용"하여 db를 해제하는 것입니다.
vapcguy

2
@vapcguy 현재 쿼리 창이 유일한 연결 인 경우에만 해당됩니다. 이것은 일반적으로 해당되지 않습니다 (그리고 이것이 제 답변에 "연결된 SSMS 사본이 아닌지 확인하십시오").
Aaron Bertrand

20

DROP명령 을 실행할 때 현재 데이터베이스는 무엇입니까 ? 이 시도:

use master
go
drop database mydb
go

또한 삭제하려는 데이터베이스가 sa아닌 연결되어 있는지 확인하십시오 dbo.


나는 확실히 주인과 연결되어 있습니다. 데이터베이스를 삭제하기 위해 sa로 연결하지 않아도됩니다. 이것은 나에게 버그처럼 보입니다. 세션을 표시하지 않거나 사용중인 세션이 있지만 그렇지 않은 것으로 생각합니다.
tuseau

3
방금이 문제를 발견했습니다-sqlcmd 프롬프트에서 데이터베이스로 설정된 컨텍스트로 드롭 스크립트를 실행하려고했습니다! Doh
JonnyRaa

18

UI를 사용할 때 SSMS의 기능을보고 작업에 대한 스크립트를 발행하도록 지시하는 것은 어떻습니까? 다음은 DB를 마우스 오른쪽 버튼으로 클릭하고 삭제를 선택한 다음 확인란을 선택하여 기존 연결을 닫을 때 SSMS가 수행하는 작업입니다.

EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'yourdbname'
GO

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

USE [master]
GO

DROP DATABASE [yourdbname]
GO

... 물론 커밋되지 않은 트랜잭션을 롤백하는 것이
좋다고 가정

4
데이터베이스를 삭제하고 있습니다. 꽤 괜찮다고 가정합니다.
georgiosd

1
이것은 나를 위해 일했다! :)
Leonardo Trimarchi

5

나는이 상황에 여러 번 직면했으며 아래는 내가하는 일입니다.

명백한 방법이 효과가 없을 때 ..... (현 상황에서와 같이) :

sysdatabases에서 데이터베이스 ID를 찾으십시오.

그런 다음 sp_lockspid 및 dbid와 함께 인스턴스의 모든 잠금을 표시합니다.

오프라인 또는 삭제하려는 dbid로 spid를 종료하십시오.

프로세스는 약간 수동이지만 다음과 같이 자동화 할 수 있습니다.

IF OBJECT_ID('tempdb.dbo.#temp', 'U') IS NOT NULL
  DROP TABLE #temp;
create table #temp (spid int
                , dbid int
                ,ObjId bigint
                , IndId bigint
                ,Type varchar(5)
                ,resource varchar(max)
                ,Mode varchar(5)
                ,status varchar(10));
declare @dbid int
select @dbid =DB_ID(db_name())

insert into #temp
exec sp_lock

select * from #temp
where dbid = @dbid

2

처음으로 작동하는 StackOverflow에서 실제로 간단한 답변을 찾았습니다.

https://stackoverflow.com/a/7469167/261405

해당 답변의 SQL은 다음과 같습니다.

DECLARE @DatabaseName nvarchar(50)
SET @DatabaseName = N'YOUR_DABASE_NAME'

DECLARE @SQL varchar(max)

SELECT @SQL = COALESCE(@SQL,'') + 'Kill ' + Convert(varchar, SPId) + ';'
FROM MASTER..SysProcesses
WHERE DBId = DB_ID(@DatabaseName) AND SPId <> @@SPId

--Use this to see results
SELECT @SQL 
--Uncomment this to run it
--EXEC(@SQL)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.