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
Parowy
źródło
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.

Dave Mason
źródło
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.
Vinu M Shankar
źródło
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
Andrei Karcheuski
źródło
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.

Aayush Verma
źródło
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 ...

Aqeel Haider
źródło
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
Jason
źródło
2

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

BabaNew
źródło
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
Puneeth
źródło
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.

Joseph Joy
źródło
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”.

Jeffrey Harmon
źródło
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;
NonProgrammer
źródło
0

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

user3790083
źródło
0

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

przejść do trybu offline

Ali Karaca
źródło