it-swarm.com.de

SQL Server Die Datenbank <Datenbankname> kann nicht gelöscht werden, da sie derzeit verwendet wird. Es werden jedoch keine Sitzungen angezeigt

Wenn ich versuche, eine Datenbank zu löschen, wird die Fehlermeldung "Datenbank" Datenbankname kann nicht gelöscht werden, da sie derzeit verwendet wird "angezeigt. Wenn ich jedoch sp_who2 Ausführe, sind definitiv keine Sitzungen mit dieser Datenbank verbunden. Ich habe auch die Datenbank auf single_user mode with rollback immediate Gesetzt.

Warum passiert dies?

81
tuseau

Stellen Sie sicher, dass Sie keine Abhängigkeiten wie Datenbank-Snapshots von der Datenbank haben, die Sie entfernen möchten. Die Fehlermeldung würde jedoch anders aussehen. Sind Sie sicher, dass es keinen versteckten Prozess gibt, der eine Verbindung zu Ihrer Datenbank herstellt? Ein guter Ansatz wäre, ein Skript auszuführen, das alle Sitzungen beendet und die Datenbank unmittelbar nach dem Umbenennen in einen anderen Namen umbenennt und dann die Datenbank löscht.

erstellen Sie einen Cursor basierend auf dieser Auswahl:

  select  d.name , convert (smallint, req_spid) As spid
      from master.dbo.syslockinfo l, 
           master.dbo.spt_values v,
           master.dbo.spt_values x, 
           master.dbo.spt_values u, 
           master.dbo.sysdatabases d
      where   l.rsc_type = v.number 
      and v.type = 'LR' 
      and l.req_status = x.number 
      and x.type = 'LS' 
      and l.req_mode + 1 = u.number
      and u.type = 'L' 
      and l.rsc_dbid = d.dbid 
      and rsc_dbid = (select top 1 dbid from 
                      master..sysdatabases 
                      where name like 'my_db')

problem im Cursor:

SET @kill_process =  'KILL ' + @spid      
            EXEC master.dbo.sp_executesql @kill_process
                   PRINT 'killed spid : '+ @spid

nachdem der Cursor geschlossen und freigegeben wurde:

sp_dboption 'my_db', 'single user', 'TRUE'

go

sp_renamedb 'my_db', 'my_db_old'

go

DROP DATABASE MY_DB_OLD 
22
yrushka

Eine mit einer anderen Datenbank verbundene Sitzung verfügt möglicherweise über eine offene Transaktion, die sich auch auf Ihre Datenbank auswirkt. Sp_who2 zeigt nur eine Datenbank an. Es könnte auch so einfach sein wie Objekt-Explorer oder Objekt-Explorer-Details, die in SSMS geöffnet sind und wiederum nur eine Datenbank in sp_who2 anzeigen.

Versuchen Sie nicht, finden die verantwortliche Sitzung zu finden; Beenden Sie sie einfach alle mit einer Anweisung (und stellen Sie sicher, dass nicht Ihre Kopie von SSMS verbunden ist, z. B. ein anderes Abfragefenster, Objekt-Explorer usw.):

USE master;
GO
ALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO

Jetzt können Sie es löschen und dies mit DDL tun, nicht mit der Benutzeroberfläche:

DROP DATABASE dbname;
92
Aaron Bertrand

Was ist Ihre aktuelle Datenbank, wenn Sie den Befehl DROP ausgeben? Versuche dies:

use master
go
drop database mydb
go

Stellen Sie außerdem sicher, dass Sie als sa und nicht als dbo in der Datenbank verbunden sind, die Sie löschen möchten.

20
Gaius

Wie wäre es, wenn Sie nur sehen, was SSMS tut, wenn Sie die Benutzeroberfläche verwenden, es aber anweisen, ein Skript für die Aktion auszugeben? Folgendes tut SSMS, wenn Sie mit der rechten Maustaste auf die Datenbank klicken und Löschen auswählen und dann das Kontrollkästchen aktivieren, um vorhandene Verbindungen zu schließen:

EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'yourdbname'
GO

USE [master]
GO
ALTER DATABASE [yourdbname] SET  SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

USE [master]
GO

DROP DATABASE [yourdbname]
GO
18
Thiago Silva

Ich habe diese Situation viele Male erlebt und im Folgenden ist, was ich tue:

Wenn offensichtliche Methoden nicht funktionieren ..... (genau wie in Ihrer Situation) :

Ermitteln Sie die Datenbank-ID aus sysdatabases.

Führen Sie dann - sp_lock, das alle Sperren der Instanz zusammen mit spid und dbid anzeigt.

Töte die Spids mit dem dbid, das du offline oder fallen lassen willst.

Obwohl der Prozess etwas manuell ist, kann er wie folgt automatisiert werden:

IF OBJECT_ID('tempdb.dbo.#temp', 'U') IS NOT NULL
  DROP TABLE #temp;
create table #temp (spid int
                , dbid int
                ,ObjId bigint
                , IndId bigint
                ,Type varchar(5)
                ,resource varchar(max)
                ,Mode varchar(5)
                ,status varchar(10));
declare @dbid int
select @dbid =DB_ID(db_name())

insert into #temp
exec sp_lock

select * from #temp
where dbid = @dbid
5
Kin Shah

Ich habe auf StackOverflow eine wirklich einfache Antwort gefunden, die beim ersten Mal für mich funktioniert hat:

https://stackoverflow.com/a/7469167/261405

Hier ist die SQL aus dieser Antwort:

DECLARE @DatabaseName nvarchar(50)
SET @DatabaseName = N'YOUR_DABASE_NAME'

DECLARE @SQL varchar(max)

SELECT @SQL = COALESCE(@SQL,'') + 'Kill ' + Convert(varchar, SPId) + ';'
FROM MASTER..SysProcesses
WHERE DBId = DB_ID(@DatabaseName) AND SPId <> @@SPId

--Use this to see results
SELECT @SQL 
--Uncomment this to run it
--EXEC(@SQL)
3
Adrian Carr