Come si interrompono tutte le connessioni correnti a un database di SQL Server 2005?


288

Voglio rinominare un database, ma continuo a ricevere l'errore che "impossibile ottenere il blocco esclusivo" sul database, il che implica che ci sono ancora connessioni attive.

Come posso eliminare tutte le connessioni al database in modo da poterlo rinominare?

Risposte:


378

La ragione per cui l'approccio che Adam ha suggerito non funzionerà è che durante il tempo in cui si esegue il loop sulle connessioni attive è possibile stabilire una nuova, e queste ti mancheranno. È possibile invece utilizzare il seguente approccio che non presenta questo inconveniente:

-- 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
Non sembra funzionare per SQL Server 2008 ... Ecco l'errore che ho riscontrato: Console: Messaggio 102, Livello 15, Stato 1, Riga 4 Sintassi errata vicino a "-". Messaggio 319, livello 15, stato 1, riga 4 Sintassi errata vicino alla parola chiave "con". Se questa istruzione è un'espressione di tabella comune, una clausola xmlnamespaces o una clausola di contesto per il rilevamento delle modifiche, l'istruzione precedente deve essere terminata con un punto e virgola. Messaggio 102, livello 15, stato 1, riga 4 Sintassi errata vicino a "IMMEDIATO". Comando: ALTER DATABASE ASMR-wdanda SET SINGLE_USER CON ROLLBACK IMMEDIATO
Wagner da Silva

Ho appena eseguito questo nel 2008 senza problemi ALTER DATABASE aspnetdb SET SINGLE_USER CON ROLLBACK IMMEDIATE seleziona GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER cosa hai al posto del codice commentato?
SQLMenace,

Ha funzionato per me con SQL Server 2008 e l'istanza di SQL Express.
Tim Murphy,

19
@Wagner se il database ha un '-' nel nome è necessario utilizzare parentesi attorno ad esso: ALTER DATABASE [foo-bar] SET SINGLE_USER CON ROLLBACK IMMEDIATO
Ben Challenor

14
Nota: NON provarlo su SQL Server ospitato su Amazon RDS. Non sarà possibile ripristinare il DB in modalità MULTI_USER. Assicurati di disporre di un altro set di credenziali DBA prima di provare. Ho risolto il problema ripristinando una delle precedenti istantanee. Perso alcuni dati. Fortunatamente i dati non erano critici.
RuntimeException il

110

Script per eseguire ciò, sostituire "DB_NAME" con il database per interrompere tutte le connessioni a:

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
Questo ha funzionato per me, ho aggiunto and spid <> @@SPIDa SELECT @sKillConnectionstatement in modo che non tentasse di interrompere la mia connessione corrente, che avrebbe generato un messaggio di errore.
Luis Perez,

Solo i processi utente possono essere interrotti ... ancora bloccati e non è possibile ripristinare la modalità multiutente a causa del deadlock.
Rainabba,

mateuscb- l'unico modo in cui non funzionerà su mssql 10.00 è se hai un nome di database che richiede [] e non li usi. ALTER DATABASE [YourDatabase] SET SINGLE_USER CON ROLLBACK IMMEDIATE funziona in 10, 10.5, 11 e 12.
Jeremy,

Salvavita. Dovrebbe essere la risposta migliore.
gls123

55

Uccidilo e uccidilo con il fuoco:

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

Utilizzando SQL Management Studio Express:

Nella struttura ad albero dell'Explorer eseguire il drill down in Gestione su "Activity Monitor" (se non lo si trova, fare clic con il tasto destro del mouse sul server di database e selezionare "Activity Monitor"). Aprendo Activity Monitor, è possibile visualizzare tutte le informazioni sul processo. Dovresti essere in grado di trovare i blocchi per il database che ti interessa e uccidere quei blocchi, che uccideranno anche la connessione.

Dovresti essere in grado di rinominare dopo quello.


Non vedo questo elemento "Monitoraggio attività" in Gestione ... Ancora una volta, forse è perché sto usando SQL 2008?
Wagner da Silva,

14
Ho trovato "Activity Montior" se fai clic con il pulsante destro del mouse sul SERVER, non sul DB. È quindi possibile selezionare la scheda "Processi" e filtrare per Database.
alirobe,

Apparentemente devi interrompere uno per uno il processo in stallo, ma è un metodo semplice che non richiede l'accesso locale o che porta il server database completo inattivo.
Álvaro González,

24

Ho sempre usato:


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 

21
ALTER DATABASE [Test]
SET OFFLINE WITH ROLLBACK IMMEDIATE

ALTER DATABASE [Test]
SET ONLINE

14

Mettere offline richiede un po 'di tempo e a volte ho dei problemi con quello ...

Il modo più solido secondo me:

Scollega Tasto destro del mouse DB -> Attività -> Scollega ... seleziona "Elimina connessioni" Ok

Ricollega Database Destro -> Allega .. Aggiungi ... -> seleziona il tuo database e cambia la colonna Allega come con il nome del database desiderato. Ok


Mi piace. Il modo più rapido per farlo dalla GUI di sicuro.
Whelkaholism

Esso funziona magicamente! Il modo semplice è il modo giusto. Grazie.
Rimorchia forte il

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

usa il database 'master' ed esegui questa query, ucciderà tutte le connessioni attive dal tuo database.


1
Funziona davvero :) Vorrei però consigliare, di mantenere commentata la parte di esecuzione di questo script e di inserire una stampa @query, solo per essere sicuri di non eseguirla su un server di produzione per errore.
Marcello Miorelli,

5

Di solito mi imbatto in quell'errore quando provo a ripristinare un database Di solito vado semplicemente in cima all'albero in Management Studio e faccio clic con il pulsante destro del mouse e riavvio del server di database (poiché si trova su una macchina di sviluppo, questo potrebbe non essere l'ideale in produzione ). Questo è vicino a tutte le connessioni al database.


Grazie, ha funzionato (i ALTER DATABASE ... SET SINGLE_USERcomandi in altre risposte hanno restituito lo stesso errore "Impossibile ottenere il blocco esclusivo").
Tinister,

4

In MS SQL Server Management Studio su Esplora oggetti, fare clic con il tasto destro del mouse sul database. Nel menu contestuale che segue selezionare 'Attività -> Take Offline'


4
Non puoi farlo se c'è una connessione attiva.
alirobe,

4

Un altro approccio "uccidilo con il fuoco" è semplicemente riavviare il servizio MSSQLSERVER. Mi piace fare cose dalla riga di comando. Incollare esattamente questo in CMD lo farà: NET STOP MSSQLSERVER e NET START MSSQLSERVER

Oppure apri "services.msc" e trova "SQL Server (MSSQLSERVER)" e fai clic con il tasto destro del mouse, seleziona "riavvia".

Questo "sicuramente," ucciderà TUTTE le connessioni a TUTTI i database in esecuzione su quell'istanza.

(Mi piace meglio di molti approcci che cambiano e cambiano la configurazione sul server / database)


Cosa intendi con "non raccomandato"? Se non sei preoccupato per le connessioni a quel server (ad esempio: ambienti di debug o di gestione temporanea, ad esempio - o un server di produzione con tempi di inattività della temperatura), questo potrebbe essere il modo più semplice. Per la produzione - non vuoi essere confuso con la configurazione se puoi semplicemente riavviare il servizio. Cosa faresti?
aikeru,

1
Vorrei cercare qualsiasi cosa che riguardi SOLO il mio DB di destinazione. il tuo approccio all'uccisione di tutti i DB sul server di destinazione non è così intelligente. ma ad essere sincero, negli ambienti di messa in scena, questo forse è il modo più semplice come hai detto.
Mohammed Swillam,

4

Ecco come fare in modo affidabile questo genere di cose in MS SQL Server Management Studio 2008 (potrebbe funzionare anche per altre versioni):

  1. Nella struttura ad Esplora oggetti, fare clic con il pulsante destro del mouse sul server database radice (con la freccia verde), quindi fare clic su Monitor attività.
  2. Apri la scheda Processi nel monitor attività, seleziona il menu a discesa "Database" e filtra in base al database desiderato.
  3. Fare clic con il tasto destro sul DB in Esplora oggetti e avviare un'attività "Attività -> Non in linea". Lascia questo in esecuzione in background mentre ...
  4. Chiudi in sicurezza tutto ciò che puoi.
  5. Uccidi tutti i processi rimanenti dalla scheda del processo.
  6. Riporta online il DB.
  7. Rinomina il DB.
  8. Riporta il tuo servizio online e indirizzalo al nuovo DB.

3

L'opzione che funziona per me in questo scenario è la seguente:

  1. Avviare l'operazione "Stacca" sul database in questione. Questo aprirà una finestra (in SQL 2005) che mostra le connessioni attive che impediscono azioni sul DB.
  2. Uccidere le connessioni attive, annullare l'operazione di distacco.
  3. Il database dovrebbe ora essere disponibile per il ripristino.

In SQL 2008 Management Studio, per qualche motivo non è più possibile accedere alla connessione attiva dalla schermata "Stacca". Funziona benissimo nel 2005 ed è così che l'ho sempre fatto, fino a quando non abbiamo effettuato l'aggiornamento al 2008 e ora tutto ciò che ricevi è un messaggio stupido che ti dice di chiudere la connessione, ma non ti consente di aprire i dettagli della connessione per interrompere ogni connessione .
Jim,


2

Fare clic con il tasto destro sul nome del database, fare clic su Proprietà per ottenere la finestra delle proprietà, Aprire la scheda Opzioni e modificare la proprietà "Limita accesso" da Multiutente a Singolo utente. Quando premi il pulsante OK, ti verrà chiesto di chiudere tutte le connessioni aperte, selezionare "Sì" e sei pronto per rinominare il database ....


2

Questi non hanno funzionato per me (SQL2008 Enterprise), inoltre non sono riuscito a vedere alcun processo in esecuzione o utenti collegati al DB. Il riavvio del server (fare clic con il tasto destro del mouse su SQL Server in Management Studio e selezionare Riavvia) mi ha permesso di ripristinare il DB.



0

Uso sp_who per ottenere l'elenco di tutti i processi nel database. Questo è meglio perché potresti voler rivedere quale processo uccidere.

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

Risultato
È possibile utilizzare il comando nella colonna KillCommand per terminare il processo desiderato.

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

-1

È possibile utilizzare il comando SP_Who e terminare tutti i processi che utilizzano il database, quindi rinominare il database.

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.