it-swarm-eu.dev

SQL Server Nelze přetáhnout databázi <název_databáze>, protože se aktuálně používá ... ale nezobrazují se žádné relace

Při pokusu o vyřazení databáze se zobrazí chyba „Nelze zrušit databázi“ dbname ”, protože se právě používá. Když však spustím sp_who2, k této databázi rozhodně nejsou žádné relace. Také jsem nastavil databázi na single_user mode with rollback immediate.

Proč se toto děje?

81
tuseau

Ujistěte se, že na db, který chcete odebrat, nemáte závislosti, jako jsou databázové snímky. Přesto by chybová zpráva vypadala jinak. Jste si jisti, že k vaší databázi není žádný skrytý proces? Dobrým přístupem by bylo spuštění skriptu, který zabije všechny relace a ihned po přejmenování databáze na jiné jméno a poté přetažení databáze.

vytvořte kurzor na základě tohoto výběru:

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

vydání uvnitř kurzoru:

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

po uzavření kurzoru a uvolnění:

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

go

sp_renamedb 'my_db', 'my_db_old'

go

DROP DATABASE MY_DB_OLD 
22
yrushka

Relace připojená k jiné databázi může mít otevřenou transakci, která také ovlivní vaši databázi - sp_who2 zobrazí pouze jednu databázi. Mohlo by to být také něco tak jednoduchého jako Object Explorer nebo Object Explorer Details otevřené v SSMS, které by znovu zobrazilo pouze jednu databázi v sp_who2.

Neobtěžujte se pokusit najít relaci, která je zodpovědná; prostě je všechny zabijte jedním příkazem (a ujistěte se, že to není vaše kopie SSMS, která je připojena, např. jiné okno dotazu, Průzkumník objektů atd.):

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

Nyní to budete moci zrušit a udělat to pomocí DDL, nikoli UI:

DROP DATABASE dbname;
92
Aaron Bertrand

Jaká je vaše aktuální databáze, když zadáte příkaz DROP? Zkuste to:

use master
go
drop database mydb
go

Také se ujistěte, že jste připojeni jako sa a ne dbo do kterékoli databáze, kterou chcete zahodit.

20
Gaius

Co takhle vidět, co SSMS dělá, když používáte UI, ale řekněte mu, aby vydal akci pro akci? Zde je to, co SSMS dělá, když kliknete pravým tlačítkem na DB a vyberete Odstranit, pak zaškrtnutím políčka uzavřete existující připojení:

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

Mnohokrát jsem čelil této situaci:

Když zřejmé metody nefungují ..... (stejně jako ve vaší situaci):

Vyhledejte ID databáze ze sysdatabases.

Poté spusťte - sp_lock, které zobrazí všechny zámky v instanci spolu se spid a dbid.

Zabijte spids pomocí dbid, které se pokoušíte offline nebo upustit.

Přestože je tento proces trochu manuální, lze jej automatizovat takto:

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

Na StackOverflow jsem našel opravdu jednoduchou odpověď, která mi pracovala poprvé:

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

Zde je SQL z této odpovědi:

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