Як ви знищуєте всі поточні підключення до бази даних SQL Server 2005?


288

Я хочу перейменувати базу даних, але продовжую отримувати помилку, що "не вдалося отримати ексклюзивний замок" у базі даних, що означає, що деякі зв’язки все ще активні.

Як я можу вбити всі підключення до бази даних, щоб перейменувати її?

Відповіді:


378

Причина того, що підхід, запропонований Адамом , не спрацює, полягає в тому, що за час, коли ви перебираєте активні з'єднання, можна встановити нове, і ви їх пропустите. Ви можете замість цього використати такий підхід, у якого немає цього недоліку:

-- 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
Схоже, це не працює для SQL Server 2008 ... Ось я отримав помилку: консоль: Msg 102, рівень 15, стан 1, рядок 4 Неправильний синтаксис біля '-'. Повідомлення 319, рівень 15, стан 1, рядок 4 Неправильний синтаксис біля ключового слова "з". Якщо цей оператор є загальним виразом таблиці, застереженням пробілів xmlnames або контекстом застереження зміни зміни, попередній вислів повинен бути закінчений крапкою з комою. Повідомлення 102, рівень 15, стан 1, рядок 4 Неправильний синтаксис поблизу "IMMEDIATE". Команда: ПОВЕРНЕННЯ ДАТАБАЗІЇ ASMR-wdanda SET SINGLE_USER З НЕЗАБАВЛЕННЯМ ВІДКЛЮЧЕННЯ
Вагнер да Сілва

Я щойно запустив це на 2008 рік без проблем НАПРАВИТИ ДАТАБАСУ aspnetdb SET SINGLE_USER З НЕЗАБАВЛЕНОЮ РОБОЧОЮ ОБРАЗУВАННЯ виберіть GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER що у вас замість коментованого коду?
SQLMenace

Для мене працював із екземпляром SQL Server 2008 та SQL Express.
Тім Мерфі

19
@Wagner, якщо в базі даних є ім'я "-", вам потрібно використовувати дужки навколо неї: ALTER DATABASE [foo-bar] SET SINGLE_USER С НЕБЕЗПЕЧЕННЯ ROLLBACK
Ben Challenor

14
Зверніть увагу: НЕ намагайтеся це робити на SQL сервері, розміщеному на Amazon RDS. Ви не зможете повернути БД до режиму MULTI_USER. Переконайтеся, що у вас є інший набір облікових даних DBA перед тим, як спробувати. Я вирішив це, повернувшись до одного з попередніх знімків. Втрачено деякі дані. На щастя, дані не були критичними.
RuntimeException

110

Сценарій для цього, замініть "DB_NAME" на базу даних, щоб знищити всі з'єднання з:

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
Це працювало для мене, я додав and spid <> @@SPIDдо SELECT @sKillConnectionзаяви, щоб він не намагався вбити моє поточне з'єднання, що породжувало б повідомлення про помилку.
Луїс Перес

Тільки користувацькі процеси можуть бути вбиті ... все ще в тупику і не може відновити режим багатокористувача через тупик.
rainabba

mateuscb - єдиний спосіб, коли він не працюватиме на mssql 10.00, це якщо у вас є ім’я бази даних, яка вимагає [], і ви їх не використовуєте. ALTER DATABASE [YourDatabase] SET SINGLE_USER AND IMEEDIATE ROLLBACK працює в 10, 10.5, 11 та 12.
Джеремі

Рятувальник. Повинно відповісти.
gls123

55

Вбити його та вбити вогнем:

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

Використання SQL Management Studio Express:

У діалоговому вікні «Об’єкт провідника» виберіть пункт «Керування активністю» («Керування активністю») (якщо ви не можете його знайти, натисніть правою кнопкою миші на сервері баз даних і виберіть «Монітор активності»). Відкривши Монітор активності, ви можете переглянути всю інформацію про процес. Ви маєте змогу знайти блоки для бази даних, яка вас цікавить, і вбити ці блоки, які також вб'ють з'єднання.

Ви повинні мати змогу перейменувати після цього.


Я не бачу цього пункту "Монітор активності" під управлінням ... Знову, можливо, це тому, що я використовую SQL 2008?
Вагнер-да-Сільва

14
Я знайшов "Монітор активності", якщо ви клацніть правою кнопкою миші СЕРВЕР, а не БД. Потім ви можете вибрати вкладку "Процеси" і відфільтрувати по базі даних.
аліробе

Вам, мабуть, потрібно по черзі вбивати застопорений процес, але це простий метод, який не вимагає локального входу або збиття повного сервера баз даних.
Альваро Гонсалес

24

Я завжди використовував:


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 


14

Займайтеся офлайн займає деякий час, і іноді у мене виникають проблеми з цим.

На мою думку, найбільш солідний спосіб:

Від'єднати Клацніть правою кнопкою миші DB -> Завдання -> Detach ... встановіть прапорець "Скасувати з'єднання" Ок

Знову клацніть правою кнопкою миші Бази даних -> Вкласти .. Додати ... -> виберіть базу даних та змініть стовпчик "Вкласти як" на потрібне ім'я бази даних. Гаразд


Люблю це. Найшвидший спосіб зробити це з GUI точно.
Whelkaholism

Це працює як шарм! Простий спосіб - хороший шлях. Дякую.
Буксир сильно

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

скористайтеся базовою базою даних та запустіть цей запит, він знищить усі активні з'єднання з вашою базою даних.


1
Це дійсно працює :) Я б радив, однак, щоб уникнути коментованої частини цього сценарію і замість цього поставити print @query, просто щоб бути впевненим, що ви не запустите це на виробничому сервері помилково.
Марчелло Міореллі

5

Я зазвичай стикаюся з цією помилкою, коли я намагаюся відновити базу даних, я зазвичай просто переходжу до верхівки дерева в студії управління і клацніть правою кнопкою миші та перезавантажте сервер бази даних (оскільки це на машині розробки, це може бути не ідеально у виробництві ). Це закриває всі підключення до бази даних.


Дякую, це спрацювало ( ALTER DATABASE ... SET SINGLE_USERкоманди в інших відповідях повернули ту саму помилку "не вдалося отримати ексклюзивний замок").
Тиністер

4

У студії управління MS SQL Server на Explorer Explorer клацніть правою кнопкою миші на базі даних. У наступному контекстному меню виберіть "Завдання -> Зайняти офлайн"


4
Ви не можете цього зробити, якщо є активне з'єднання.
аліробе

4

Ще один підхід "вбити вогнем" - це просто перезапустити службу MSSQLSERVER. Мені подобається робити речі з командного рядка. Вставивши це точно в CMD, це вдасться: NET STOP MSSQLSERVER & NET START MSSQLSERVER

Або відкрийте "services.msc" і знайдіть "SQL Server (MSSQLSERVER)" і клацніть правою кнопкою миші, виберіть "перезапустити".

Це "точно, точно" знищить ВСІ з'єднання до ВСІХ баз даних, що працюють у цьому екземплярі.

(Мені це подобається більше, ніж багато підходів, які змінюють і змінюють назад конфігурацію на сервері / базі даних)


Що означає "не рекомендується"? Якщо ви не переймаєтесь будь-якими підключеннями до цього сервера (наприклад, налагодження або встановлення середовища, наприклад - або виробничий сервер із тимчасовим простоєм), це може бути найпростішим способом. Для виробництва - ви не хочете спілкуватися з конфігурацією, якщо зможете просто перезапустити послугу. Що б ти зробив?
aikeru

1
Я б пішов на все, що може вплинути ТІЛЬКИ на мій цільовий БД. ваш підхід убити всі БД на цільовому сервері не такий розумний. але чесно кажучи, в постановковому середовищі це, можливо, найпростіший спосіб, як ви сказали.
Мухаммед Свіллам

4

Ось як надійно подібні речі в MS SQL Server Management Studio 2008 (можуть працювати і для інших версій):

  1. У дереві провідника об’єктів клацніть правою кнопкою миші сервер кореневої бази даних (зеленою стрілкою), а потім натисніть на монітор активності.
  2. Відкрийте вкладку процесів на моніторі діяльності, виберіть спадне меню "Бази даних" та відфільтруйте потрібну базу даних.
  3. Клацніть правою кнопкою миші БД у Провіднику об’єктів та запустіть завдання «Завдання -> Зайняти офлайн». Залиште це працювати у фоновому режимі, поки ви ...
  4. Безпечно вимкніть все, що тільки можете.
  5. Вбити всі процеси, що залишилися, на вкладці "Процес".
  6. Поверніть БД назад.
  7. Перейменуйте БД.
  8. Поверніть свою послугу в Інтернет і вкажіть її на нову БД.

3

Варіант, який працює для мене в цьому сценарії, такий:

  1. Почніть операцію "Від'єднати" на відповідній базі даних. Це відкриє вікно (у SQL 2005) із відображенням активних з'єднань, що перешкоджає дії над БД.
  2. Вбийте активні з'єднання, скасуйте операцію від'єднання.
  3. Тепер база даних повинна бути доступною для відновлення.

У студії управління SQL 2008 ви з певних причин більше не можете отримувати доступ до активного з'єднання з екрана "Від'єднати". Це чудово працює в 2005 році, і ось так я завжди робив, до моменту оновлення до 2008 року, і тепер все, що ви отримуєте, - це дурне повідомлення, яке говорить про те, щоб закрити з'єднання, але не дозволяє вам відкрити деталі з'єднання, щоб знищити кожне з'єднання. .
Джим


2

Клацніть правою кнопкою миші на ім'я бази даних, натисніть на вікно Властивості, щоб отримати властивість, відкрийте вкладку Параметри та змініть властивість "Обмежити доступ" з "Користувача на багато користувачів" на "Один користувач". Якщо натиснути кнопку ОК, вона запропонує вам закрити все відкрите з'єднання, виберіть "Так" і ви налаштовані на перейменування бази даних ....


2

Вони не працювали для мене (SQL2008 Enterprise), я також не міг бачити жодних запущених процесів або користувачів, підключених до БД. Перезапуск сервера (Клацніть правою кнопкою миші на сервер Sql в студії управління та виберіть «Перезапустити») дозволив відновити БД.



0

Я використовую sp_who, щоб отримати список усіх процесів у базі даних. Це краще, тому що ви можете переглянути, який процес вбити.

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

Результат
Ви можете використовувати команду в стовпці KillCommand, щоб знищити потрібний процес.

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

-1

Ви можете використовувати команду SP_Who і вбити весь процес, який використовує вашу базу даних, а потім перейменувати вашу базу даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.