SQL Server无法删除数据库<dbname>,因为它当前正在使用中……但是未显示任何会话


72

当我尝试删除数据库时,出现错误“无法删除数据库“ dbname”,因为它当前正在使用”。但是,当我运行时sp_who2,肯定没有连接到该数据库的会话。我还将数据库设置为single_user mode with rollback immediate

为什么会这样呢?

Answers:


20

确保您没有要删除的数据库上的数据库快照之类的依赖项。虽然,错误消息将看起来相反。您确定没有隐藏的进程正在连接到数据库吗?一个好的方法是运行一个脚本,该脚本杀死所有会话,并在将数据库重命名为另一个名称后立即删除数据库。

根据此选择创建一个游标:

  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 2011年

是的,通常您应该能够通过sp_who或从master db查询sysprocesses表来查看所有活动/非活动状态。“隐藏”是指与应用程序服务重新连接的过程。干杯。
yrushka

1
这是过时的,其原因有多个:(1)旧式联接(2)向后兼容视图(3)当单个ALTER可以执行时,游标和动态SQL运行一堆KILL命令(4)不建议使用的过程,例如sp_dboption。
亚伦·伯特兰

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

现在,您将能够删除它,并使用DDL而不是UI进行删除:

DROP DATABASE dbname;

1
感谢您的回答,此方法有效。但是我在使用该解决方案方面遇到了困难:为什么为什么由于这个错误而无法删除某些数据库?我有一些未使用过一年的数据库,没有任何与之相关的过程或表面交易。您能否给我一些提示,以帮助我找到潜在的服务,交易或与这些数据库相关的任何东西?
LearnByReading

1
其实,所有我需要做的就是USE master,那么DROP DATABASE dbname。显然,所需要做的就是仅“使用”其他东西来释放数据库。
vapcguy

2
@vapcguy仅当您当前的查询窗口是唯一的连接时才如此。通常不是这种情况(这就是为什么我的回答指出“并确保不是所连接的SSMS副本”)。
亚伦·伯特兰

20

发出DROP命令时,当前的数据库是什么?尝试这个:

use master
go
drop database mydb
go

另外,请确保您已连接,sa而不要连接dbo到您要删除的任何数据库。


我肯定和师父有联系。我不必以sa身份连接即可删除数据库。在我看来,这就像一个错误-它不显示会话,或者认为正在使用会话,但没有使用。
tuseau 2011年

3
我刚刚发现了这一点-尝试从sqlcmd提示符运行将上下文设置为数据库的drop脚本!Doh
JonnyRaa 2014年

18

仅在使用UI时看到SSMS的功能,然后告诉它发出操作脚本,该怎么办?右键单击数据库并选择“删除”,然后选中此框以关闭现有连接,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

……当然,可以回滚未提交的交易
swasheck

4
您正在删除数据库,我认为它还不错。
georgiosd

1
这对我有用!:)
莱昂纳多·特里玛其

5

我已经多次遇到这种情况,下面是我的工作:

当明显的方法不起作用时(就像您所处的情况一样):

从sysdatabases中找到数据库ID。

然后执行- sp_lock将显示实例上的所有锁以及spid和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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.