¿Cómo se eliminan todas las conexiones actuales a una base de datos de SQL Server 2005?


288

Quiero cambiar el nombre de una base de datos, pero sigo recibiendo el error 'no se pudo obtener el bloqueo exclusivo' en la base de datos, lo que implica que todavía hay algunas conexiones activas.

¿Cómo puedo eliminar todas las conexiones a la base de datos para poder cambiarle el nombre?

Respuestas:


378

La razón por la que el enfoque que sugirió Adam no funcionará es que durante el tiempo que está haciendo un bucle sobre las conexiones activas, se puede establecer una nueva, y las perderá. En su lugar, podría usar el siguiente enfoque que no tiene este inconveniente:

-- 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
Eso no parece funcionar para SQL Server 2008 ... Aquí está el error que obtuve: Consola: Mensaje 102, Nivel 15, Estado 1, Línea 4 Sintaxis incorrecta cerca de '-'. Mensaje 319, Nivel 15, Estado 1, Línea 4 Sintaxis incorrecta cerca de la palabra clave 'con'. Si esta declaración es una expresión de tabla común, una cláusula xmlnamespaces o una cláusula de contexto de seguimiento de cambios, la declaración anterior debe terminarse con un punto y coma. Mensaje 102, Nivel 15, Estado 1, Línea 4 Sintaxis incorrecta cerca de 'INMEDIATO'. Comando: ALTER DATABASE ASMR-wdanda SET SINGLE_USER WITH ROLLBACK INMEDIATE
Wagner da Silva

Acabo de ejecutar esto en 2008 sin problemas ALTER DATABASE aspnetdb SET SINGLE_USER WITH ROLLBACK INMEDIATE select GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER ¿qué tienes en lugar del código comentado?
SQLMenace

Me funcionó con SQL Server 2008 y la instancia de SQL Express.
Tim Murphy

19
@Wagner si la base de datos tiene un '-' en el nombre, debe usar corchetes alrededor: ALTER DATABASE [foo-bar] SET SINGLE_USER WITH ROLLBACK INMEDIATE
Ben Challenor

14
Tenga en cuenta: NO intente esto en el servidor SQL alojado en Amazon RDS. No podrá restablecer la base de datos al modo MULTI_USER. Asegúrese de tener otro conjunto de credenciales de DBA antes de intentar esto. Lo arreglé volviendo a una de las instantáneas anteriores. Perdí algunos datos. Afortunadamente, los datos no fueron críticos.
RuntimeException

110

Script para lograr esto, reemplace 'DB_NAME' con la base de datos para eliminar todas las conexiones a:

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
Esto funcionó para mí, agregué and spid <> @@SPIDa la SELECT @sKillConnectiondeclaración para que no intentara matar mi conexión actual, lo que generaría un mensaje de error.
Luis Pérez

Solo los procesos de usuario pueden ser eliminados ... aún estancados y no pueden restaurar el modo multiusuario debido a un punto muerto.
rainabba

mateuscb: la única forma en que no funcionará en mssql 10.00 es si tiene un nombre de base de datos que requiere [] y no los usa. ALTER DATABASE [YourDatabase] SET SINGLE_USER WITH ROLLBACK INMEDIATE funciona en 10, 10.5, 11 y 12.
Jeremy

Salvador de la vida. Debería ser la mejor respuesta.
gls123

55

Mátalo y mátalo con fuego:

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

Usando SQL Management Studio Express:

En el árbol del Explorador de objetos, desglose en Gestión hasta "Monitor de actividad" (si no puede encontrarlo allí, haga clic con el botón derecho en el servidor de la base de datos y seleccione "Monitor de actividad"). Al abrir el Monitor de actividad, puede ver toda la información del proceso. Debería poder encontrar los bloqueos para la base de datos que le interesa y eliminar esos bloqueos, lo que también eliminará la conexión.

Debería poder cambiar el nombre después de eso.


No veo este elemento "Monitor de actividad" en Administración ... De nuevo, ¿tal vez es porque estoy usando SQL 2008?
Wagner da Silva

14
He encontrado una "Actividad Montior" si hace clic derecho en el SERVIDOR, no en el DB. Luego puede seleccionar la pestaña 'Procesos' y filtrar por Base de datos.
alirobe

Aparentemente, debe eliminar el proceso estancado uno por uno, pero es un método sencillo que no requiere inicio de sesión local o la caída del servidor de base de datos completo.
Álvaro González

24

Siempre he usado:


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

Desconectarse lleva un tiempo y a veces tengo algunos problemas con eso ...

La forma más sólida en mi opinión:

Separar Haga clic derecho en DB -> Tareas -> Separar ... marque "Soltar conexiones" Ok

Vuelva a adjuntar Haga clic con el botón derecho en Bases de datos -> Adjuntar .. Agregar ... -> seleccione su base de datos y cambie la columna Adjuntar como a su nombre de base de datos deseado. Okay


Gusta. La forma más rápida de hacerlo desde la GUI seguro.
Whelkaholism

¡Funciona a las mil maravillas! El camino fácil es el buen camino. Gracias.
Tug Strongly

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

use la base de datos 'maestra' y ejecute esta consulta, eliminará todas las conexiones activas de su base de datos.


1
Realmente funciona :) Sin embargo, le aconsejaría que mantuviera comentada la parte de ejecución de este script y coloque un print @query en su lugar, solo para asegurarse de que no lo ejecute en un servidor de producción por error.
Marcello Miorelli

5

Por lo general, me encuentro con ese error cuando estoy tratando de restaurar una base de datos. Por lo general, solo voy a la parte superior del árbol en Management Studio y hago clic derecho y reinicio el servidor de la base de datos (porque está en una máquina de desarrollo, esto podría no ser ideal en producción ) Esto cierra todas las conexiones de la base de datos.


Gracias, esto funcionó (los ALTER DATABASE ... SET SINGLE_USERcomandos en otras respuestas devolvieron el mismo error 'no se pudo obtener el bloqueo exclusivo').
Tinister

4

En MS SQL Server Management Studio en el explorador de objetos, haga clic derecho en la base de datos. En el menú contextual que sigue, seleccione 'Tareas -> Desconectar'


44
No puede hacer esto si hay una conexión activa.
alirobe

4

Otro enfoque de "matarlo con fuego" es simplemente reiniciar el servicio MSSQLSERVER. Me gusta hacer cosas desde la línea de comandos. Pegar esto exactamente en CMD lo hará: NET STOP MSSQLSERVER & NET START MSSQLSERVER

O abra "services.msc" y busque "SQL Server (MSSQLSERVER)" y haga clic derecho, seleccione "reiniciar".

Esto "seguro, seguro" matará TODAS las conexiones a TODAS las bases de datos que se ejecutan en esa instancia.

(Me gusta más que muchos enfoques que cambian y cambian la configuración en el servidor / base de datos)


¿Qué quieres decir con "no recomendado"? Si no le preocupan las conexiones a ese servidor (por ejemplo, entornos de depuración o almacenamiento provisional, por ejemplo, o un servidor de producción con tiempo de inactividad temporal), esta puede ser la forma más fácil. Para la producción: no querrá estar en la configuración si solo puede reiniciar el servicio. ¿Qué harías?
aikeru

1
Iría por cualquier cosa que afecte SOLO a mi DB objetivo. Su enfoque de matar todos los DB en el servidor de destino no es tan inteligente. pero para ser honesto, en entornos de puesta en escena, esta es quizás la forma más fácil como dijiste.
Mohammed Swillam

4

Aquí le mostramos cómo hacer este tipo de cosas de manera confiable en MS SQL Server Management Studio 2008 (también puede funcionar para otras versiones):

  1. En el Árbol del Explorador de objetos, haga clic con el botón derecho en el servidor de la base de datos raíz (con la flecha verde), luego haga clic en monitor de actividad.
  2. Abra la pestaña de procesos en el monitor de actividad, seleccione el menú desplegable 'bases de datos' y filtre por la base de datos que desee.
  3. Haga clic derecho en la base de datos en el Explorador de objetos y comience una tarea 'Tareas -> Desconectar'. Deja esto ejecutándose en segundo plano mientras ...
  4. Cierra de forma segura todo lo que puedas.
  5. Elimina todos los procesos restantes de la pestaña de proceso.
  6. Vuelva a poner el DB en línea.
  7. Cambie el nombre de la base de datos.
  8. Vuelva a poner su servicio en línea y apúntelo a la nueva base de datos.

3

La opción que funciona para mí en este escenario es la siguiente:

  1. Inicie la operación "Separar" en la base de datos en cuestión. Esto abrirá una ventana (en SQL 2005) que muestra las conexiones activas que evitan acciones en la base de datos.
  2. Elimine las conexiones activas, cancele la operación de desconexión.
  3. La base de datos ahora debería estar disponible para restaurar.

En SQL 2008 Management Studio, por alguna razón ya no puede acceder a la conexión activa desde la pantalla "Separar". Funciona muy bien en 2005 y así es como siempre lo hice, hasta que actualizamos a 2008 y ahora todo lo que obtienes es un mensaje estúpido que te dice que cierres tu conexión, pero no te permite abrir los detalles de la conexión para eliminar cada conexión. .
Jim


2

Haga clic derecho en el nombre de la base de datos, haga clic en Propiedad para obtener la ventana de propiedades, abra la pestaña Opciones y cambie la propiedad "Restringir acceso" de Usuario múltiple a Usuario único. Cuando presiona el botón OK, le pedirá que cierre todas las conexiones abiertas, seleccione "Sí" y estará listo para cambiar el nombre de la base de datos ...


2

Esto no funcionó para mí (SQL2008 Enterprise), tampoco pude ver ningún proceso en ejecución o usuarios conectados a la base de datos. Reiniciar el servidor (haga clic con el botón derecho en Servidor SQL en Management Studio y seleccione Reiniciar) me permitió restaurar la base de datos.



0

Yo uso sp_who para obtener una lista de todos los procesos en la base de datos. Esto es mejor porque es posible que desee revisar qué proceso matar.

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

Resultado
Puede usar el comando en la columna KillCommand para eliminar el proceso que desea.

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

-1

Puede usar el comando SP_Who y eliminar todos los procesos que usan su base de datos y luego cambiarle el nombre.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.