如何终止当前与SQL Server 2005数据库的所有连接?


288

我想重命名数据库,但不断收到错误消息“数据库无法获得排他锁”,这意味着仍有一些连接处于活动状态。

如何终止与数据库的所有连接,以便可以对其重命名?

Answers:


378

亚当建议的方法行不通的原因是,当您在活动连接上循环时,可以建立新的连接,而您会错过这些连接。您可以改用以下方法,但没有此缺点:

-- set your current connection to use master otherwise you might get an error

use master
ALTER DATABASE YourDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE 

--do you stuff here 

ALTER DATABASE YourDatabase SET MULTI_USER

1
这似乎不适用于SQL Server 2008 ...这是我收到的错误:控制台:消息102,级别15,状态1,第4行'-'附近的语法不正确。消息319,级别15,状态1,第4行关键字“ with”附近的语法错误。如果此语句是公用表表达式,xmlnamespaces子句或更改跟踪上下文子句,则前一条语句必须以分号终止。消息102,级别15,状态1,第4行'IMMEDIATE'附近的语法不正确。命令:ALTER DATABASE ASMR-wdanda SET SINGLE_USER,具有立即回滚功能
Wagner da Silva,2010年

我只是在2008年就运行了,没有任何问题ALTER DATABASE aspnetdb SET SINGLE_USER ROLLBACK IMMEDIATE选择GETDATE()ALTER DATABASE aspnetdb SET MULTI_USER您有什么而不​​是注释掉的代码?
SQLMenace 2010年

为我使用SQL Server 2008和SQL Express实例。
Tim Murphy

19
@Wagner如果数据库名称中带有“-”,则需要在其周围使用方括号:ALTER DATABASE [foo-bar] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Ben Challenor

14
请注意-请勿在Amazon RDS托管的SQL Server上尝试此操作。您将无法将数据库重置回MULTI_USER模式。尝试执行此操作之前,请确保您具有另一组DBA凭据。我通过恢复为以前的快照之一来解决此问题。丢失了一些数据。幸运的是,数据并不重要。
RuntimeException 2014年

110

为此,请用脚本替换“ DB_NAME”以终止与以下数据库的所有连接:

USE master
GO

SET NOCOUNT ON
DECLARE @DBName varchar(50)
DECLARE @spidstr varchar(8000)
DECLARE @ConnKilled smallint
SET @ConnKilled=0
SET @spidstr = ''

Set @DBName = 'DB_NAME'
IF db_id(@DBName) < 4
BEGIN
PRINT 'Connections to system databases cannot be killed'
RETURN
END
SELECT @spidstr=coalesce(@spidstr,',' )+'kill '+convert(varchar, spid)+ '; '
FROM master..sysprocesses WHERE dbid=db_id(@DBName)

IF LEN(@spidstr) > 0
BEGIN
EXEC(@spidstr)
SELECT @ConnKilled = COUNT(1)
FROM master..sysprocesses WHERE dbid=db_id(@DBName)
END

1
这对我有用,我添加and spid <> @@SPIDSELECT @sKillConnection语句中,这样它就不会尝试终止我当前的连接,这会生成错误消息。
路易斯·佩雷斯

只有用户进程才能被杀死...仍然处于死锁状态,由于死锁而无法恢复多用户模式。
rainabba

mateuscb-在mssql 10.00上不起作用的唯一方法是,如果您的数据库名称需要[]并且不使用它们。ALTER DATABASE [YourDatabase] SET SINGLE_USER与ROLLBACK IMMEDIATE可以在10、10.5、11和12中使用。–
Jeremy

救生员。应该是最佳答案。
gls123

55

杀死它,然后用火杀死它:

USE master
go

DECLARE @dbname sysname
SET @dbname = 'yourdbname'

DECLARE @spid int
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname)
WHILE @spid IS NOT NULL
BEGIN
EXECUTE ('KILL ' + @spid)
SELECT @spid = min(spid) from master.dbo.sysprocesses where dbid = db_id(@dbname) AND spid > @spid
END

27

使用SQL Management Studio Express:

在“对象资源管理器”树中,在“管理”下向下钻取到“活动监视器”(如果在那里找不到它,则右键单击数据库服务器并选择“活动监视器”)。打开活动监视器,您可以查看所有过程信息。您应该能够找到您感兴趣的数据库的锁,并杀死这些锁,这也会终止连接。

之后,您应该可以重命名。


我在“管理”下没有看到“活动监视器”项。再次,也许是因为我使用的是SQL 2008?
瓦格纳·席尔瓦

14
如果您右键单击服务器而不是数据库,我会发现一个“ Activity Montior”。然后,您可以选择“进程”选项卡并按数据库进行过滤。
alirobe

您显然需要一个一个地杀死停滞的进程,但这是一种简单的方法,不需要本地登录或关闭整个数据库服务器。
阿尔瓦罗·冈萨雷斯

24

我一直使用:


ALTER DATABASE DB_NAME SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
GO 
SP_RENAMEDB 'DB_NAME','DB_NAME_NEW'
Go 
ALTER DATABASE DB_NAME_NEW  SET MULTI_USER -- set back to multi user 
GO 

21
ALTER DATABASE [Test]
SET OFFLINE WITH ROLLBACK IMMEDIATE

ALTER DATABASE [Test]
SET ONLINE

14

离线需要一段时间,有时我会遇到一些问题。

我认为最可靠的方法是:

分离 右键单击DB->任务->分离...选中“删除连接”,确定

重新 附加右键单击数据库->附加...。添加...->选择数据库,然后将“附加为”列更改为所需的数据库名称。好


喜欢它。确保从GUI最快的方法。
Whelkaholism

它就像一个魅力!简单的方法就是好方法。谢谢。
猛拉力

6
Select 'Kill '+ CAST(p.spid AS VARCHAR)KillCommand into #temp
from master.dbo.sysprocesses p (nolock)
join master..sysdatabases d (nolock) on p.dbid = d.dbid
Where d.[name] = 'your db name'

Declare @query nvarchar(max)
--Select * from #temp
Select @query =STUFF((                              
            select '  ' + KillCommand from #temp
            FOR XML PATH('')),1,1,'') 
Execute sp_executesql @query 
Drop table #temp

使用“主”数据库并运行此查询,它将杀死数据库中的所有活动连接。


1
它确实有效:)不过,我还是建议您保留此脚本的执行部分注释,并改用打印@query,以确保您不会在生产服务器上错误地运行它。
Marcello Miorelli 2014年

5

在尝试还原数据库时,通常会遇到该错误,我通常只是移至M​​anagement Studio中树的顶部,然后右键单击并重新启动数据库服务器(因为它在开发机器上,因此在生产中可能并不理想) )。这将关闭所有数据库连接。


谢谢,这行得通(ALTER DATABASE ... SET SINGLE_USER其他答案中的命令返回了相同的“无法获取排他锁”错误)。
Tinister

4

在对象浏览器上的MS SQL Server Management Studio中,右键单击数据库。在随后的上下文菜单中,选择“任务->脱机”


4
如果存在活动连接,则无法执行此操作。
alirobe

4

另一种“用火杀死它”的方法是仅重新启动MSSQLSERVER服务。我喜欢从命令行执行操作。将其完全粘贴到CMD中即可:NET STOP MSSQLSERVER和NET START MSSQLSERVER

或打开“ services.msc”并找到“ SQL Server(MSSQLSERVER)”,然后单击鼠标右键,选择“重新启动”。

这将“确定,确定”终止与该实例上运行的所有数据库的所有连接。

(我比许多更改和更改服务器/数据库上的配置的方法更喜欢这种方法)


您是什么意思“不推荐”?如果您不关心与该服务器的任何连接(例如:调试或登台环境-或具有临时停机时间的生产服务器),这可能是最简单的方法。对于生产-如果您可以重新启动服务,则不希望浪费配置。你会怎么做?
aikeru 2013年

1
我会尝试只影响目标数据库的任何事情。您杀死目标服务器上所有数据库的方法并不明智。但老实说,在登台环境中,这可能是您所说的最简单的方法。
Mohammed Swillam

4

这是在MS SQL Server Management Studio 2008中可靠地进行此类操作的方法(也可能适用于其他版本):

  1. 在“对象资源管理器树”中,右键单击根数据库服务器(带有绿色箭头),然后单击“活动监视器”。
  2. 在活动监视器中打开“进程”选项卡,选择“数据库”下拉菜单,然后按所需的数据库进行过滤。
  3. 在对象资源管理器中右键单击数据库,然后启动“任务->使离线”任务。在您执行以下操作时,让它在后台运行
  4. 尽一切可能安全关闭。
  5. 从“进程”选项卡中杀死所有剩余的进程。
  6. 使数据库重新联机。
  7. 重命名数据库。
  8. 使您的服务重新联机,并将其指向新的数据库。

3

在这种情况下为我工作的选项如下:

  1. 在有关的数据库上启动“分离”操作。这将打开一个窗口(在SQL 2005中),该窗口显示活动的连接,从而阻止对DB进行操作。
  2. 终止活动连接,取消分离操作。
  3. 该数据库现在应该可以还原了。

在SQL 2008 Management Studio中,由于某种原因,您无法再从“分离”屏幕访问活动连接。它在2005年运作良好,这就是我一直以来的做法,直到我们升级到2008年,现在您得到的只是一条愚蠢的消息,告诉您关闭连接,但不允许您打开连接详细信息以终止每个连接。
吉姆(Jim


2

右键单击数据库名称,单击“属性”以获取属性窗口,打开“选项”选项卡,然后将“限制访问”属性从“多用户”更改为“单用户”。当您单击“确定”按钮时,它将提示您关闭所有打开的连接,选择“是”,并设置为重命名数据库...。


2

这些对我不起作用(SQL2008 Enterprise),我也看不到任何正在运行的进程或连接到数据库的用户。重新启动服务器(在Management Studio中右键单击Sql Server,然后选择“重新启动”)使我可以还原数据库。



0

我使用sp_who获取数据库中所有进程的列表。这样比较好,因为您可能需要查看要终止的进程。

declare @proc table(
    SPID bigint,
    Status nvarchar(255),
    Login nvarchar(255),
    HostName nvarchar(255),
    BlkBy nvarchar(255),
    DBName nvarchar(255),
    Command nvarchar(MAX),
    CPUTime bigint,
    DiskIO bigint,
    LastBatch nvarchar(255),
    ProgramName nvarchar(255),
    SPID2 bigint,
    REQUESTID bigint
)

insert into @proc
exec sp_who2

select  *, KillCommand = concat('kill ', SPID, ';')
from    @proc

结果
您可以在KillCommand列中使用command杀死想要的进程。

SPID    KillCommand
26      kill 26;
27      kill 27;
28      kill 28;

-1

您可以使用SP_Who命令并杀死使用数据库的所有进程,然后重命名数据库。

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.