Hola, chicos,
Buenas noches.
Hoy vengo a traer un consejo rápido para aquellos que querían hacer una restauración rápida, alterar una base de datos o cualquier comando que requiera un bloqueo exclusivo en una base de datos, pero había usuarios ejecutando consultas en la base de datos, y luego recibe un mensaje de error como este de SQL Server:
Mensaje 3101, Nivel 16, Estado 1, Línea 2
No se pudo obtener acceso exclusivo porque la base de datos está en uso.
Mensaje 3013, Nivel 16, Estado 1, Línea 2
RESTORE DATABASE está finalizando de forma anormal.
En este caso, debemos asegurarnos de que todas las conexiones existentes que utilizan esta base de datos estén desconectadas y luego intentar ejecutar nuestro comando nuevamente. La mejor forma de hacerlo es contactando a los usuarios y alineando sus necesidades para que cierren sus conexiones y terminen de ejecutar sus consultas.
Nunca se recomienda KILL conexiones sin el consentimiento de los usuarios, a menos que sea algo crítico o un mantenimiento programado que ya se haya programado previamente.
Eliminar conexiones de una base de datos mediante KILL
Si realmente es necesario eliminar manualmente las conexiones que utilizan una base de datos, puedes utilizar este pequeño fragmento de código T-SQL para realizar esta tarea:
DECLARE @query VARCHAR(MAX) = ''
SELECT
@query = COALESCE(@query, ',') + 'KILL ' + CONVERT(VARCHAR, spid) + '; '
FROM
master..sysprocesses
WHERE
dbid = DB_ID('Testes') -- Nome do database
AND dbid > 4 -- Não eliminar sessões em databases de sistema
AND spid <> @@SPID -- Não eliminar a sua própria sessão
IF (LEN(@query) > 0)
EXEC(@query)
Eliminar conexiones de una base de datos a través de ALTER DATABASE
El comando anterior es muy práctico y funciona sin problemas. Sin embargo, entre el momento en que elimina las sesiones y ejecuta RESTORE DATABASE, por ejemplo, otras conexiones pueden conectarse a la base de datos. Por esta razón, el método más recomendado para esta operación es con ALTER DATABASE, colocando la base de datos en modo SINGLE_USER, donde solo puede conectarse un único usuario a la vez:
ALTER DATABASE Testes SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
El parámetro CON ROLLBACK IMMEDIATE hace que todas las sesiones se cierren sin previo aviso y se reviertan inmediatamente. Ahora podrás realizar tu mantenimiento sin posibilidad de que ninguna otra conexión interfiera con tus comandos. Al finalizar tu mantenimiento, recuerda devolver el banco al modo MULTI_USUARIO, para que pueda aceptar múltiples conexiones nuevamente:
ALTER DATABASE Testes SET MULTI_USER
GO
Eliminar todas las conexiones de todas las bases de datos
Como beneficio adicional, publicaré aquí dos soluciones para eliminar todas las sesiones de todas las bases de datos (excepto las del sistema).
Vía MATAR:
DECLARE @query VARCHAR(MAX) = ''
SELECT
@query = COALESCE(@query, ',') + 'KILL ' + CONVERT(VARCHAR, spid) + '; '
FROM
master..sysprocesses
WHERE
dbid > 4 -- Não eliminar sessões em databases de sistema
AND spid <> @@SPID -- Não eliminar a sua própria sessão
IF (LEN(@query) > 0)
EXEC(@query)
A través de ALTER BASE DE DATOS:
Colocar todas las bases de datos de instancia en modo SINGLE_USER:
EXEC sp_msforeachdb '
IF (DB_ID(''?'') > 4)
EXEC (''ALTER DATABASE [?] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;'')'
Devolver todas las bases de datos de instancia al modo MULTI_USER:
En este caso, no pude utilizar el procedimiento almacenado sp_msforeachdb, ya que no lista las bases de datos en modo SINGLE_USER. En este caso, tuve que recorrer manualmente las bases de datos.
IF (OBJECT_ID('tempdb..#Databases') IS NOT NULL) DROP TABLE #Databases
SELECT IDENTITY(INT, 1,1) AS Id, name
INTO #Databases
FROM sys.sysdatabases
WHERE dbid > 4 -- Ignorar databases de sistema
DECLARE
@Contador INT = 1,
@Total_Databases INT = (SELECT COUNT(*) FROM #Databases),
@Query VARCHAR(MAX)
WHILE(@Contador <= @Total_Databases)
BEGIN
SELECT @Query = 'ALTER DATABASE [' + name + '] SET MULTI_USER;'
FROM #Databases
WHERE Id = @Contador
EXEC(@Query)
SET @Contador = @Contador + 1
END
Eso es todo, queridos lectores.
¡Hasta la próxima!
Comentários (0)
Carregando comentários…