У меня есть база данных для разработки, которая часто переустанавливается из проекта базы данных Visual Studio (через TFS Auto Build).
Иногда, когда я запускаю свою сборку, я получаю эту ошибку:
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.
Я попробовал это:
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
но я все еще не могу удалить базу данных. (Я предполагаю, что большинство разработчиков имеют dbo
доступ.)
Я могу вручную запускать SP_WHO
и запускать уничтожение соединений, но мне нужен автоматический способ сделать это в автоматической сборке. (Хотя на этот раз мое соединение - единственное в БД, которое я пытаюсь разорвать.)
Есть ли сценарий, который может отбросить мою базу данных независимо от того, кто подключен?
kill
заявлений всех вместе. Я бы использовал курсор для уничтожения каждого процесса, что, конечно, неэффективно. Техника, использованная в этом ответе, блестящая.USE [Master]
Ссылка: http://msdn.microsoft.com/en-us/library/bb522682%28v=sql.105%29.aspx
источник
USE master
был ключ. Я пытался сбросить БД при подключении к нему (Дух!). Спасибо!SET OFFLINE
вы должны вручную удалить файлы БД.alter database YourDatabaseName set SINGLE_USER with rollback immediate
будет лучше? Если вы установите егоOFFLINE
(как утверждает @mattalxndr), файлы будут оставлены на диске, но сSINGLE_USER
вашим подключением останется единственным, иdrop database YourDatabaseName
все равно удалит файлы.set offline
вы можете выполнитьset online
эту проблему, чтобы избежать проблемы с оставшимися файлами (да, существует возможность состояния гонки).Вы можете получить скрипт, который предоставляет SSMS, выполнив следующие действия:
Сценарий будет выглядеть примерно так:
источник
Малоизвестно: оператор GO sql может принимать целое число для повторения предыдущей команды.
Так что если вы:
Затем:
Это будет повторять команду USE 2000 раз, вызывать взаимоблокировку всех других соединений и переходить во владение одним соединением. (Предоставление вашему окну запроса единственного доступа к действиям, которые вы хотите.)
источник
По моему опыту, использование SINGLE_USER в большинстве случаев помогает, однако, следует быть осторожным: у меня были случаи, когда между временем, когда я запускаю команду SINGLE_USER, и временем, когда она закончена ... очевидно, другой «пользователь» получил SINGLE_USER доступ, а не я. Если это произойдет, вам придется выполнить сложную работу, пытаясь вернуть доступ к базе данных (в моем случае это была специальная служба, работающая для программного обеспечения с базами данных SQL, которая получила доступ SINGLE_USER раньше, чем я). То, что я думаю, должно быть самым надежным способом (не могу ручаться за это, но это то, что я проверю в ближайшие дни), на самом деле:
- остановите службы, которые могут помешать вашему доступу (если они есть)
- используйте скрипт «kill» выше, чтобы закрыть все соединения
- сразу после этого установите базу данных в single_user
- затем выполните восстановление
источник
В высшей степени эффективный сценарий Мэтью обновлен для использования DMV dm_exec_sessions, заменив устаревшую системную таблицу sysprocesses:
Альтернативно использование цикла WHILE (если вы хотите обрабатывать любые другие операции за выполнение):
источник
Принятый ответ имеет недостаток, заключающийся в том, что он не принимает во внимание, что база данных может быть заблокирована соединением, которое выполняет запрос, который включает таблицы в базе данных, отличной от той, к которой подключен.
Это может быть в том случае, если экземпляр сервера имеет более одной базы данных и запрос прямо или косвенно (например, через синонимы) использует таблицы в более чем одной базе данных и т. Д.
Поэтому я считаю, что иногда лучше использовать syslockinfo для поиска соединений, которые нужно уничтожить.
Поэтому я предложил бы использовать приведенный ниже вариант принятого ответа от AlexK:
источник
sys.dm_tran_locks
таблицу,syslockinfo
которая помечена как устаревшая, вы также можете исключить ваш текущий @@ SPID на всякий случай.Вы должны быть осторожны с исключениями во время процессов убийства. Таким образом, вы можете использовать этот скрипт:
источник
@AlexK написал отличный ответ . Я просто хочу добавить свои два цента. Приведенный ниже код полностью основан на ответе @ AlexK, разница в том, что вы можете указать пользователя и время с момента последнего выполнения пакета (обратите внимание, что код использует sys.dm_exec_sessions вместо master..sysprocess):
В этом примере будет уничтожен только процесс пользователя usrDBTest, последний пакет которого был выполнен более 1 часа назад.
источник
Вы можете использовать Курсор так:
Я написал об этом в своем блоге здесь: http://www.pigeonsql.com/single-post/2016/12/13/Kill-all-connections-on-DB-by-Cursor
источник
источник
Я успешно протестировал с простым кодом ниже
источник
set SINGLE_USER
когда уже было единственное активное соединение.