Błąd - nie można uzyskać dostępu na wyłączność, ponieważ baza danych jest używana


120

W rzeczywistości próbuję utworzyć skrypt (w Sql Server 2008), aby przywrócić jedną bazę danych z jednego pliku kopii zapasowej. Wykonałem następujący kod i otrzymuję błąd -

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.

Jak rozwiązać ten problem?

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

Jeśli uda mi się to uruchomić, być może uda mi się stworzyć niezawodny skrypt do przywrócenia wielu baz danych z jednego folderu. Nie mogłem znaleźć żadnego wiarygodnego kodu w sieci. Mój kod może być niezawodny, ponieważ jest generowany przez samo SS.
Steam

Odpowiedzi:


106

Zakładam, że jeśli przywracasz bazę danych, nie obchodzą Cię żadne istniejące transakcje na tej bazie danych. Dobrze? Jeśli tak, to powinno działać dla Ciebie:

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

A teraz jeszcze jedna rzecz, o której należy pamiętać. Po ustawieniu bazy danych w tryb pojedynczego użytkownika ktoś inny może próbować połączyć się z bazą danych. Jeśli się powiedzie, nie będzie można kontynuować przywracania. To wyścig! Proponuję uruchomić wszystkie trzy instrukcje naraz.


wszystkie trzy oświadczenia w transakcji.
Steam

1
Mój SSMS przechodzi w tryb braku odpowiedzi za każdym razem, gdy próbuję uzyskać dostęp do bazy danych Adventureworks.
Steam

2
Właściwie ma na myśli USE master, że nie USER master.
async

7
Po prostu dodaj ALTER DATABASE [AdventureWorksDW] SET MULTI_USERna końcu, aby upewnić się, że baza danych wróci do normalnego trybu wielu użytkowników.
gnaanaa

1
@gnaanaa: Jeśli kopia zapasowa bazy danych była w SINGLE_USERtrybie podczas tworzenia kopii zapasowej, będzie w SINGLE_USERtrybie podczas przywracania kopii zapasowej. Jeśli był w MULTI_USERtrybie w czasie tworzenia kopii zapasowej, będzie w MULTI_USERtrybie po przywróceniu. Masz świetną uwagę: zdecydowanie warto sprawdzić po zakończeniu przywracania. Możesz także uruchomić RESTORE HEADERONLY na nośniku kopii zapasowej i sprawdzić IsSingleUserlub wykonać bitowe obliczenia matematyczne na Flagskolumnie.
Dave Mason

237
  1. Ustaw ścieżkę do przywrócenia pliku.
  2. Kliknij „Opcje” po lewej stronie.
  3. Odznacz „Przed przywróceniem wykonaj kopię zapasową dziennika końcowego”
  4. Zaznacz pole wyboru - "Zamknij istniejące połączenia z docelową bazą danych". wprowadź opis obrazu tutaj
  5. Kliknij OK.

16
W moim przypadku to pole wyboru było wyszarzone. Jednak zacząłem od nowa i mogłem zaznaczyć pole wyboru przed wybraniem źródła do przywrócenia. Po wybraniu pliku kopii zapasowej opcja była ponownie wyszarzona, ale pole było nadal zaznaczone, a przywracanie działało.
phansen

3
Brawa za uratowanie mnie przed pisaniem SQL. Jedyna metoda GUI spośród wszystkich odpowiedzi.
Lionet Chen

Mam nadzieję, że zadziałałoby to dla mnie jak inne. Ale dla mnie to pole wyboru zawsze pozostawało wyszarzone. Poniższa odpowiedź Andrieja Karchueuskiego zadziałała dla mnie.
Devraj Gadhavi

11
Musiałem również odznaczyć opcję „Wykonaj kopię zapasową dziennika końcowego przed przywróceniem”, zanim udało mi się przywrócić.
Hylle,

3
„Wykonaj kopię zapasową dziennika końcowego przed przywróceniem”, to również musi być odznaczone. Dzięki
jedu

50

wykonaj to zapytanie przed przywróceniem bazy danych:

alter database [YourDBName] 
set offline with rollback immediate

a ten po przywróceniu:

  alter database [YourDBName] 
  set online

Skończyło się na przełączeniu na tę metodę przez SINGLE_USER po tym, jak połączenie aplikacji pilotażowej pokonało przywracanie mojego zapytania i kolejne wywołanie MULTI_USER. Podczas przywracania nie udało się uzyskać wyłącznego dostępu, a stara baza danych została w trybie SINGLE_USER.
Smörgåsbord

3
to działało dla mnie. i przechodzi do trybu online automatycznie po przywróceniu.
Dileep

3
To działa i pozwala uniknąć sytuacji wyścigu w zaakceptowanej odpowiedzi.
Scott Whitlock,

1
Dziękuję Andrei.
Erdogan

11

Dla mnie rozwiązaniem jest:

  1. Zaznacz opcję Zastąp istniejącą bazę danych (Z WYMIENIĄ) w zakładce optoins po lewej stronie.

  2. Odznacz wszystkie inne opcje.

  3. Wybierz źródłową i docelową bazę danych.

  4. Kliknij OK.

Otóż ​​to.


1
U mnie też zadziałało. Musiałem również odznaczyć opcję „Wykonaj kopię zapasową dziennika końcowego przed przywróceniem”.
yuva,

7

Użyj następującego skryptu, aby znaleźć i zabić wszystkie otwarte połączenia z bazą danych przed przywróceniem bazy danych.

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...'

Mam nadzieję, że to pomoże ...


3

Myślę, że przed próbą przywrócenia wystarczy ustawić bazę danych w trybie pojedynczego użytkownika, jak poniżej, po prostu upewnij się, że używasz master

USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER

2

Właśnie ponownie uruchomiłem usługę sqlexpress, a następnie przywracanie zakończyło się pomyślnie


co mogę powiedzieć o głosowaniu przeciw ... dla mnie zadziałało!
BabaNew

1
OP miał problem ze swoim skryptem przywracania, ponieważ nie wziął pod uwagę faktu, że jego baza danych może być już używana. Rozwiązaniem było zaktualizowanie jego skryptu za pomocą odpowiednich poleceń umożliwiających mu wyłączny dostęp do bazy danych. Ponowne uruchomienie usługi mogło Ci pomóc, ale nie było to właściwe rozwiązanie jego problemu.
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

Rozwiązanie 1: Uruchom ponownie usługi SQL i spróbuj przywrócić bazę danych Rozwiązanie 2: Uruchom ponownie system / serwer i spróbuj przywrócić bazę danych Rozwiązanie 3: Przywróć bieżącą bazę danych, usuń bieżącą / docelową bazę danych i spróbuj przywrócić bazę danych.


1

Ustawienie DB w tryb pojedynczego użytkownika nie działało dla mnie, ale przełączenie go w tryb offline, a następnie przywrócenie go do trybu online działało. Znajduje się w menu prawym przyciskiem myszy bazy danych, w obszarze Zadania.

Pamiętaj, aby w oknie dialogowym zaznaczyć opcję „Porzuć wszystkie aktywne połączenia”.


0

Oto sposób przywracania bazy danych z produkcji do programowania:

UWAGA: Robię to za pomocą zadania SSAS, aby codziennie wypychać produkcyjną bazę danych do programowania:

Krok 1: Usuń kopię zapasową z poprzedniego dnia w trakcie opracowywania:

declare @sql varchar(1024);

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

Krok 2: Skopiuj produkcyjną bazę danych do programowania:

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

Krok 3: Przywróć, uruchamiając skrypt .sql

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

Kod znajdujący się w pliku 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

Pojawił się ten błąd, gdy zabrakło miejsca na dysku, aby przywrócić Db. Porządkowanie przestrzeni rozwiązało problem.


0

przeniesienie oryginalnej bazy danych do trybu offline zadziałało dla mnie

przejść do trybu offline

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.