Errore: non è stato possibile ottenere l'accesso esclusivo perché il database è in uso


119

In realtà sto cercando di creare uno script (in Sql Server 2008) per ripristinare un database da un file di backup. Ho creato il seguente codice e ricevo un errore:

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.

Come risolvo questo problema?

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

Se riesco a farlo funzionare, forse posso creare uno script affidabile per ripristinare più database da una cartella. Non sono riuscito a trovare alcun codice affidabile in rete. Il mio codice potrebbe essere affidabile perché è generato da SS stesso.
Steam

Risposte:


106

Presumo che se stai ripristinando un database, non ti interessano le transazioni esistenti su quel database. Destra? In tal caso, dovrebbe funzionare per te:

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

Ora, un elemento aggiuntivo da tenere presente. Dopo aver impostato il database in modalità utente singolo, qualcun altro potrebbe tentare di connettersi al database. Se hanno successo, non sarai in grado di procedere con il ripristino. È una gara! Il mio suggerimento è di eseguire tutte e tre le istruzioni contemporaneamente.


tutte e tre le dichiarazioni in una transazione.
Steam

1
Il mio SSMS entra in modalità di non risposta ogni volta che provo ad accedere a quel database di adventureworks.
Steam

2
In realtà significa USE master, no USER master.
asincrono

7
Basta aggiungere ALTER DATABASE [AdventureWorksDW] SET MULTI_USERalla fine per assicurarsi che il database torni nella normale modalità multiutente.
gnaanaa

1
@gnaanaa: se il database di cui è stato eseguito il backup era in SINGLE_USERmodalità al momento del backup, sarà in SINGLE_USERmodalità quando il backup viene ripristinato. Se era in MULTI_USERmodalità al momento del backup, sarà in MULTI_USERmodalità quando verrà ripristinato. Fai un ottimo punto: vale sicuramente la pena controllare al termine del ripristino. È anche possibile eseguire RESTORE HEADERONLY sul supporto di backup e controllare IsSingleUsero eseguire calcoli bit-wise sulla Flagscolonna.
Dave Mason

236
  1. Imposta il percorso per ripristinare il file.
  2. Fare clic su "Opzioni" sul lato sinistro.
  3. Deseleziona "Esegui il backup della parte finale del log prima del ripristino"
  4. Spunta la casella di controllo - "Chiudi le connessioni esistenti al database di destinazione". inserisci qui la descrizione dell'immagine
  5. Fare clic su OK.

16
Nel mio caso quella casella di controllo era disattivata. Tuttavia ho ricominciato da capo e sono stato in grado di selezionare la casella prima di scegliere la fonte da cui eseguire il ripristino. Dopo aver scelto il file di backup, l'opzione è stata nuovamente disattivata, ma la casella è stata ancora selezionata e il ripristino ha funzionato.
phansen

3
Complimenti per avermi salvato dalla digitazione di SQL. L'unico metodo GUI tra tutte le risposte.
Lionet Chen

Spero che questo avrebbe funzionato per me come gli altri. Ma per me la casella di controllo è rimasta sempre disattivata. La risposta di Andrei Karchueuski di seguito, ha funzionato per me.
Devraj Gadhavi

11
Ho anche dovuto deselezionare "Esegui backup del registro finale prima del ripristino" prima di poter eseguire il ripristino.
Hylle

3
"Esegui il backup della parte finale del log prima del ripristino" deve essere deselezionato anche questo. Grazie
jedu

50

eseguire questa query prima di ripristinare il database:

alter database [YourDBName] 
set offline with rollback immediate

e questo dopo il ripristino:

  alter database [YourDBName] 
  set online

Ho finito per passare a questo metodo su SINGLE_USER dopo che la connessione dell'applicazione pilota ha superato il ripristino della mia query e la successiva chiamata MULTI_USER. Il ripristino non è riuscito a ottenere l'accesso esclusivo e il vecchio db è stato lasciato in modalità SINGLE_USER.
Smörgåsbord

3
questo ha funzionato per me. e torna online automaticamente una volta ripristinato.
Dileep

3
Funziona ed evita la race condition nella risposta accettata.
Scott Whitlock

1
Grazie Andrei.
Erdogan

11

Per me la soluzione è:

  1. Seleziona Sovrascrivi il database esistente (CON SOSTITUISCI) nella scheda Optoins sul lato sinistro.

  2. Deseleziona tutte le altre opzioni.

  3. Seleziona il database di origine e di destinazione.

  4. Fare clic su OK.

Questo è tutto.


1
Ha funzionato anche per me. Ho dovuto deselezionare anche "Esegui backup del registro finale prima del ripristino".
yuva

7

Utilizzare il seguente script per trovare e terminare tutte le connessioni aperte al database prima di ripristinare il database.

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

Spero che questo ti aiuti ...


3

Penso che tu abbia solo bisogno di impostare il db in modalità utente singolo prima di tentare di ripristinare, come di seguito, assicurati solo di utilizzare master

USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER

2

Ho appena riavviato il servizio sqlexpress e quindi il ripristino è stato completato correttamente


cosa posso dire del downvote ... per me ha funzionato!
BabaNew

1
OP ha avuto un problema con il suo script di ripristino perché non ha preso in considerazione il fatto che il suo DB potrebbe essere già in uso. La soluzione era aggiornare il suo script con i comandi appropriati che gli permettessero l'accesso esclusivo al DB. Anche se il riavvio del servizio potrebbe aver funzionato per te, quella non era la soluzione appropriata al suo problema.
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

Soluzione 1: riavviare i servizi SQL e provare a ripristinare il database Soluzione 2: riavviare il sistema / server e provare a ripristinare il database Soluzione 3: riprendere il database corrente, eliminare il database corrente / di destinazione e provare a ripristinare il database.


1

L'impostazione del DB in modalità utente singolo non ha funzionato per me, ma portarlo offline e poi riportarlo online ha funzionato. Si trova nel menu di scelta rapida del DB, sotto Attività.

Assicurati di selezionare l'opzione "Elimina tutte le connessioni attive" nella finestra di dialogo.


0

Ecco un modo in cui eseguo il ripristino del database dalla produzione allo sviluppo:

NOTA: lo sto facendo tramite il lavoro SSAS per inviare quotidianamente il database di produzione allo sviluppo:

Passaggio 1: eliminare il backup del giorno precedente in fase di sviluppo:

declare @sql varchar(1024);

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

Passaggio 2: copia il database di produzione nello sviluppo:

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

Passaggio 3: ripristinare eseguendo lo script .sql

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

Codice contenuto nel file 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

Ho ricevuto questo errore quando non c'era abbastanza spazio su disco per ripristinare Db. Pulire un po 'di spazio lo ha risolto.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.