Está en la página 1de 7

Forzar el Cierre de conexiones en SQL

Server
Publicado el 13 octubre, 2012 por Angel Camilo Bernal Serna

[ad]

Cuando trabajamos con SQL server, muchas veces nos damos cuenta que las operaciones
que se van a realizar requieren acceso exclusivo. En lo personal, me ocurre generalmente
cuando trato de restaurar una base de datos sobre una base de datos que actualmente está en
uso, pero puede ocurrir con otro tipo de tareas.

La verdad es frustrante encontrar el aviso que indica que la base de datos está en uso:

Bueno, pues para este problema existen varias soluciones; en este post vamos a revisar 2 de
ellas.

Para cualquiera de las 2 soluciones que planteo, hay que tener en cuenta varios elementos:

1. El proceso de cierre de conexiones puede tardar un poco dependiendo de las


transacciones que se encuentren activas en el momento del cierre de las conexiones.
2. Al cerrar las conexiones activas, existe una gran posibilidad de que el trabajo de
otros usuarios se pierda, lo anterior debido a que el motor de base de datos debe
reversar las transacciones que estén en curso en el momento del cierre de las
conexiones.

Teniendo en cuenta lo anterior, ya podemos revisar los 2 métodos que propongo:

1. Por un lado, se puede pensar en poner temporalmente la base de datos en modo


“Single User”; mediante esta acción (por defecto las bases de datos en SQL Server
se crean en modo “MultiUser”) el motor de base de datos cierra todas las
conexiones existentes a la base de datos.
2. El otro método, consiste en “Matar” los procesos de usuario que tienen conexiones
abiertas en la base de datos.

Para el caso del método A, lo podemos llevar a cabo desde el Microsoft® SQL Server
Management Studio (MSSMS) cambiando las opciones de la base de datos:
1. Clic derecho sobre la base de datos donde deseamos cerrar las conexiones
2. En la página de “Opciones” de la ventana de propiedades, buscamos la entrada
“Restrict Access”; por defecto estará en “MULTI_USER”
3. Seteamos la opción “Restrict Access” a “SINGLE_USER” y damos “Ok”

4. Una vez damos clic en “Ok”, el motor de base de datos nos va a indicar que para
aplicar el cambio sobre la base de datos deberá cerrar todas las demás (excepto la
nuestra) conexiones a dicha base de datos, genial, esto es lo que queremos que haga.
Damos clic en “Yes” (para los que lo tengan en español, esto equivale a dar clic en
“Si” jejeje. )

5. Una vez aceptamos el motor cerrará todas las conexiones y colocará un icono
especial sobre la base de datos en la que acabamos de aplicar los cambios
Este icono nos indica que la base de datos esta en modo “Single User”.

Ahora ya podemos realizar las tareas que deseemos en la base de datos; es importante tener
en cuenta que mientras no se reverse la acción que acabamos de realizar ningún usuario
(salvo tú) va a poder tener acceso a la base de datos. Para volver a dejar la base de datos en
el estado original, basta con realizar nuevamente los pasos descritos atrás y poner en
“Restrict Access” en modo “MULTI_USER”.

Para quienes prefieran el código en vez de la interfaz gráfica, todos los pasos anteriores
tienen su equivalente en código T-SQL; en lo personal, siempre prefiero el código ya que
me obliga a estar aprendiendo nuevas sentencias día a día. He aquí el código equivalente
para pasar de “MULTI USER” A “SINGLE USER” y viceversa:

Para pasar de “MULTI USER” a “SINGLE USER”:


USE [master]

GO

ALTERDATABASE [{NOMBRE_DE_TU_BASE_DE_DATOS}] SET SINGLE_USER WITH


ROLLBACK IMMEDIATE

GO
Para pasar de “SINGLE USER” a “MULTI USER”:
USE [master]

GO

ALTERDATABASE [{NOMBRE_DE_TU_BASE_DE_DATOS}] SET MULTI_USER WITH ROLLBACK


IMMEDIATE

GO

Para el caso del método B (la opción de “matar” los procesos), consiste en unas sencillas
sentencias T-SQL y hacer uso de la instrucción “Kill”, que como su nombre lo indica (y
como lo indica también la documentación de MSDN en: http://msdn.microsoft.com/es-
es/library/ms173730.aspx) se encarga de “Matar” o terminar los procesos y/o las
conexiones “normales”.

Dado que la instrucción “Kill” debe recibir como parámetro los ID’s de las sesiones de
cuyos procesos se van a cerrar, podemos hacer una consulta a la tabla “SysProcesses” de la
base de datos “Master” para tener la lista de procesos activos asociados a la base de datos
que necesitamos; para filtrar los resultados de la consulta a fin de matar solamente los
procesos de nuestra base de datos, vamos a utilizar el campo “DBId” (el id de la base de
datos). Para extraer el nombre como tal de la base de datos, podemos hacer uso de la
función DB_NAME() que recibe como parámetro el Id de la base de datos. Como para
matar los procesos solo necesitamos el Id del proceso, este se encuentra en el campo spid
de la tabla “SysProcesses”. Al final, la lista de procesos a “matar” la obtendremos del
siguiente query:

select spid from master..SysProcesses WHERE DB_NAME(DBId)=‘{NOMBRE_DE_TU_BASE_DE_DATOS}’

Ahora, para evitarnos la tarea de matar uno por uno los procesos, podemos crear una
instrucción que se encargue de matar los procesos del query por nosotros, lo anterior, lo
logramos creando una instrucción “kill” por cada registro resultante y luego concatenar
todos los “kill” en una cadena de texto que al final ejecutaremos con el comando “exec”
así:

USE[Master]

GO

DECLARE @KillCommandSQL VARCHAR(max)

SELECT @KillCommandSQL = COALESCE(@KillCommandSQL,”) + ‘ KILL


‘+convert(VARCHAR(10),spid)+' ‘

FROM

master..SysProcesses
WHERE DB_NAME(DBId)=‘{NOMBRE_DE_TU_BASE_DE_DATOS}’

PRINT @KillCommandSQL

–EXEC (@KillCommandSQL)

Dónde @KillCommandSQL es la variable donde almacenaremos los comandos “Kill”; la


función “COALESCE” la utilicé para evitar errores por valores nulos
(http://technet.microsoft.com/es-es/library/ms190349.aspx) . Nótese que incluí un “Print”,
esto, para que antes de ejecutar el comando, veamos como queda finalmente, la revisemos y
evitemos errores. Ten en cuenta que el comando “EXEC” esta como comentario,
precisamente para evitar que accidentalmente lo ejecutemos, es decir que el query no
funcionará hasta tanto no le quitemos la marca de comentario.

Bueno amigos, esto es todo, espero esta entrada pueda ser de ayuda en algún momento y
que los pueda sacar de apuros en alguna situación que así lo requiera.

Si alguno de ustedes encuentra un error en algo que haya mencionado en esta entrada, o si
alguno tiene una idea alternativa para forzar el cierre de conexiones en SQL Server o si
quiere comentar como se haría en otras plataformas, por favor no dude en colocar un
comentario al final de esta entrada.

Como siempre, un gran abrazo para tod@s y… “HAPPY CODING”

También podría gustarte