Tengo una base de datos de desarrollo que se vuelve a implementar con frecuencia desde un proyecto de base de datos de Visual Studio (a través de una compilación automática TFS).
A veces, cuando ejecuto mi compilación, aparece este error:
ALTER DATABASE failed because a lock could not be placed on database 'MyDB'. Try again later.
ALTER DATABASE statement failed.
Cannot drop database "MyDB" because it is currently in use.
Intenté esto:
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
pero todavía no puedo soltar la base de datos. (Supongo que la mayoría de los desarrolladores tienen dbo
acceso).
Puedo ejecutar manualmente SP_WHO
y comenzar a eliminar conexiones, pero necesito una forma automática de hacerlo en la compilación automática. (Aunque esta vez mi conexión es la única en la base de datos que estoy tratando de eliminar).
¿Existe un script que pueda eliminar mi base de datos independientemente de quién esté conectado?
kill
declaraciones todas juntas. Usaría un cursor para matar cada proceso, que por supuesto no es eficiente en absoluto. La técnica utilizada en esta respuesta es brillante.USE [Master]
Ref: http://msdn.microsoft.com/en-us/library/bb522682%28v=sql.105%29.aspx
fuente
USE master
esa era la clave. Estaba tratando de soltar el db mientras estaba conectado a él (¡Duh!). ¡Gracias!SET OFFLINE
, debe eliminar manualmente los archivos db.alter database YourDatabaseName set SINGLE_USER with rollback immediate
sería mejor? Si lo establece enOFFLINE
(como dice @mattalxndr) los archivos se dejarán en el disco, pero conSINGLE_USER
su conexión se dejará como el único ydrop database YourDatabaseName
aún se eliminarán los archivos.set offline
, puede emitirset online
para evitar el problema de los archivos sobrantes (sí, existe la posibilidad de una condición de carrera).Puede obtener el script que SSMS proporciona haciendo lo siguiente:
El guión se verá más o menos así:
fuente
Poco conocido: la instrucción GO sql puede tomar un número entero para la cantidad de veces que se repite el comando anterior.
Así que si usted:
Luego:
Esto repetirá el comando USE 2000 veces, forzará un punto muerto en todas las demás conexiones y tomará posesión de la conexión única. (Otorgando a su ventana de consulta acceso exclusivo para hacer lo que desee).
fuente
Según mi experiencia, el uso de SINGLE_USER ayuda la mayoría de las veces, sin embargo, uno debe tener cuidado: he experimentado ocasiones en las que entre el momento en que inicio el comando SINGLE_USER y el momento en que finaliza ... aparentemente, otro 'usuario' había recibido el Acceso SINGLE_USER, no yo. Si eso sucede, te espera un trabajo difícil tratando de recuperar el acceso a la base de datos (en mi caso, se trataba de un servicio específico que se ejecutaba para un software con bases de datos SQL que se apoderó del acceso SINGLE_USER antes que yo). Lo que creo que debería ser la forma más confiable (no puedo responder por ello, pero es lo que probaré en los próximos días), es en realidad:
- detener los servicios que pueden interferir con su acceso (si hay alguno)
- use el script 'kill' anterior para cerrar todas las conexiones
- establezca la base de datos en single_user inmediatamente después de eso
- luego realice la restauración
fuente
El script sumamente eficiente de Matthew actualizado para usar el DMV dm_exec_sessions, reemplazando la tabla del sistema sysprocesses en desuso:
Alternativa al uso del ciclo WHILE (si desea procesar cualquier otra operación por ejecución):
fuente
La respuesta aceptada tiene el inconveniente de que no tiene en cuenta que una base de datos puede bloquearse mediante una conexión que está ejecutando una consulta que involucra tablas en una base de datos distinta de la que está conectada.
Este puede ser el caso si la instancia del servidor tiene más de una base de datos y la consulta directa o indirecta (por ejemplo, a través de sinónimos) usa tablas en más de una base de datos, etc.
Por lo tanto, creo que a veces es mejor usar syslockinfo para encontrar las conexiones para matar.
Por lo tanto, mi sugerencia sería utilizar la siguiente variación de la respuesta aceptada de AlexK:
fuente
sys.dm_tran_locks
tabla comosyslockinfo
está marcada como obsoleta, también, puede querer excluir su @@ SPID actual por si acaso.Debe tener cuidado con las excepciones durante los procesos de eliminación. Entonces puedes usar este script:
fuente
@AlexK escribió una gran respuesta . Solo quiero agregar mis dos centavos. El siguiente código se basa completamente en la respuesta de @ AlexK, la diferencia es que puede especificar el usuario y el tiempo desde que se ejecutó el último lote (tenga en cuenta que el código usa sys.dm_exec_sessions en lugar de master..sysprocess):
En este ejemplo, solo se eliminará el proceso del usuario usrDBTest que realizó el último lote hace más de 1 hora.
fuente
Puedes usar el cursor así:
Escribí sobre eso en mi blog aquí: http://www.pigeonsql.com/single-post/2016/12/13/Kill-all-connections-on-DB-by-Cursor
fuente
fuente
He probado con éxito con el código simple a continuación
fuente
set SINGLE_USER
cuando ya había una sola conexión activa.