Ошибка - не удалось получить монопольный доступ, поскольку база данных уже используется.


121

На самом деле я пытаюсь создать сценарий (в Sql Server 2008) для восстановления одной базы данных из одного файла резервной копии. Я ввел следующий код и получаю сообщение об ошибке -

Msg 3101, Level 16, State 1, Line 3
Exclusive access could not be obtained because 
the database is in use.
Msg 3013, Level 16, State 1, Line 3
RESTORE DATABASE is terminating abnormally.

Как мне решить эту проблему?

IF DB_ID('AdventureWorksDW') IS NOT NULL 
BEGIN 
RESTORE DATABASE [AdventureWorksDW] 
FILE = N'AdventureWorksDW_Data' 
FROM  
DISK = N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\Backup\AdventureWorksDW.bak' 
WITH  FILE = 1, 
MOVE N'AdventureWorksDW_Data' 
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW.mdf', 
MOVE N'AdventureWorksDW_Log'  
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW_0.LDF', 
NOUNLOAD,  STATS = 10 
END

Если мне удастся заставить это работать, возможно, я смогу создать надежный сценарий для восстановления нескольких баз данных из одной папки. Я не нашел в сети надежного кода. Мой код может быть надежным, потому что он генерируется самим SS.
Steam

Ответы:


106

Я предполагаю, что если вы восстанавливаете базу данных, вам не нужны никакие существующие транзакции в этой базе данных. Правильно? Если да, то это должно сработать для вас:

USE master
GO

ALTER DATABASE AdventureWorksDW
SET SINGLE_USER
--This rolls back all uncommitted transactions in the db.
WITH ROLLBACK IMMEDIATE
GO

RESTORE DATABASE AdventureWorksDW
FROM ...
...
GO

Теперь нужно знать еще об одном пункте. После того, как вы установите базу данных в однопользовательский режим, кто-то другой может попытаться подключиться к базе данных. В случае успеха вы не сможете продолжить восстановление. Это гонка! Я предлагаю запустить все три оператора одновременно.


все три оператора в транзакции.
Steam

1
Моя SSMS переходит в режим «не отвечает» всякий раз, когда я пытаюсь получить доступ к этой базе данных adventureworks.
Steam

2
На самом деле он имеет в виду USE master, что нет USER master.
async

7
Просто добавьте ALTER DATABASE [AdventureWorksDW] SET MULTI_USERв конце, чтобы убедиться, что база данных вернулась в обычный многопользовательский режим.
gnaanaa 03

1
@gnaanaa: Если SINGLE_USERрезервная копия базы данных была в режиме во время резервного копирования, она будет в SINGLE_USERрежиме, когда резервная копия будет восстановлена. Если он был в MULTI_USERрежиме во время резервного копирования, он будет в MULTI_USERрежиме после восстановления. Вы подумали: это определенно стоит проверить после завершения восстановления. Вы также можете запустить RESTORE HEADERONLY на резервном носителе и проверить столбец IsSingleUserили выполнить побитовые вычисления Flags.
Дэйв Мейсон

238
  1. Задайте путь для восстановления файла.
  2. Нажмите "Параметры" слева.
  3. Снимите флажок "Сделать резервную копию журнала перед восстановлением"
  4. Установите флажок - «Закрыть существующие подключения к целевой базе данных». введите описание изображения здесь
  5. Щелкните ОК.

16
В моем случае этот флажок был неактивен. Однако я начал заново и смог установить флажок перед выбором источника для восстановления. После выбора файла резервной копии этот параметр снова стал серым, но флажок все еще был установлен, и восстановление работало.
phansen

3
Престижность за то, что спас меня от ввода SQL. Единственный метод GUI среди всех ответов.
Lionet Chen 01

Я надеюсь, что это сработало бы для меня, как и у других. Но для меня флажок всегда оставался серым. Ответ Андрея Карчуевского ниже , сработал для меня.
Деврадж Гадхави

11
Мне также пришлось снять флажок «Сделать резервную копию хвостового журнала перед восстановлением», прежде чем я смог восстановить.
Hylle 07

3
«Сделать резервную копию хвостового журнала перед восстановлением» также необходимо снять. Спасибо
jedu

50

выполните этот запрос перед восстановлением базы данных:

alter database [YourDBName] 
set offline with rollback immediate

и этот после восстановления:

  alter database [YourDBName] 
  set online

В итоге я переключился на этот метод через SINGLE_USER после того, как соединение пилотного приложения превысило восстановление моего запроса и последующий вызов MULTI_USER. При восстановлении не удалось получить монопольный доступ, и старая база данных осталась в режиме SINGLE_USER.
Smörgåsbord

3
это сработало для меня. и он автоматически подключается к сети, как только вы его восстановите.
Дилип

3
Это работает и позволяет избежать состояния гонки в принятом ответе.
Скотт Уитлок

1
Спасибо, Андрей.
Эрдоган

11

Для меня решение:

  1. Установите флажок «Перезаписать существующую базу данных (С ЗАМЕНИТЬ)» на вкладке «Опции» слева.

  2. Снимите все флажки со всех остальных опций.

  3. Выберите исходную и целевую базы данных.

  4. Щелкните ОК.

Вот и все.


1
У меня тоже сработало. Мне также пришлось снять флажок «Сделать резервную копию хвостового журнала перед восстановлением».
yuva

7

Используйте следующий сценарий, чтобы найти и закрыть все открытые подключения к базе данных перед восстановлением базы данных.

declare @sql as varchar(20), @spid as int

select @spid = min(spid)  from master..sysprocesses  where dbid = db_id('<database_name>') 
and spid != @@spid    

while (@spid is not null)
begin
    print 'Killing process ' + cast(@spid as varchar) + ' ...'
    set @sql = 'kill ' + cast(@spid as varchar)
    exec (@sql)

    select 
        @spid = min(spid)  
    from 
        master..sysprocesses  
    where 
        dbid = db_id('<database_name>') 
        and spid != @@spid
end 

print 'Process completed...'

Надеюсь, это поможет ...


3

Я думаю, вам просто нужно установить db в однопользовательский режим, прежде чем пытаться восстановить, как показано ниже, просто убедитесь, что вы используете master

USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER

2

Я просто перезапустил службу sqlexpress, а затем восстановление завершилось нормально


что я могу сказать о голосовании против ... для меня это сработало!
BabaNew

1
У OP возникла проблема с его сценарием восстановления, потому что он не принял во внимание тот факт, что его БД, возможно, уже используется. Решение состояло в том, чтобы обновить его скрипт соответствующими командами, предоставляя ему монопольный доступ к БД. Хотя перезапуск службы мог сработать для вас, это не подходящее решение его проблемы.
PL

1
Use Master
alter database databasename set offline with rollback immediate;

--Do Actual Restore
RESTORE DATABASE databasename
FROM DISK = 'path of bak file'
WITH MOVE 'datafile_data' TO 'D:\newDATA\data.mdf',
MOVE 'logfile_Log' TO 'D:\newDATA\DATA_log.ldf',replace

alter database databasename set online with rollback immediate;
GO

1

Решение 1. Перезапустите службы SQL и попытайтесь восстановить БД. Решение 2. Перезапустите систему / сервер и попытайтесь восстановить БД. Решение 3. Верните текущую БД, удалите текущую / целевую БД и попытайтесь восстановить БД.


1

Установка БД в однопользовательский режим у меня не сработала, но перевод ее в автономный режим, а затем возврат в оперативный режим действительно сработал. Он находится в контекстном меню базы данных, в разделе «Задачи».

Обязательно установите флажок «Отменить все активные подключения» в диалоговом окне.


0

Вот способ восстановления базы данных от производства к разработке:

ПРИМЕЧАНИЕ. Я делаю это через SSAS, чтобы ежедневно запускать производственную базу данных в разработку:

Шаг 1. Удалите резервную копию предыдущего дня в разработке:

declare @sql varchar(1024);

set @sql = 'DEL C:\ProdAEandAEXdataBACKUP\AE11.bak'
exec master..xp_cmdshell @sql

Шаг 2: Скопируйте производственную базу данных в разработку:

declare @cmdstring varchar(1000)
set @cmdstring = 'copy \\Share\SQLDBBackup\AE11.bak C:\ProdAEandAEXdataBACKUP'
exec master..xp_cmdshell @cmdstring 

Шаг 3. Восстановите, запустив сценарий .sql.

SQLCMD -E -S dev-erpdata1 -b -i "C:\ProdAEandAEXdataBACKUP\AE11_Restore.sql"

Код, который находится в файле AE11_Restore.sql:

RESTORE DATABASE AE11
FROM DISK = N'C:\ProdAEandAEXdataBACKUP\AE11.bak'
WITH MOVE 'AE11' TO 'E:\SQL_DATA\AE11.mdf',
MOVE 'AE11_log' TO 'D:\SQL_LOGS\AE11.ldf',
RECOVERY;

0

Я получил эту ошибку, когда на диске не хватало места для восстановления Db. Очистка места решила эту проблему.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.