Musimy wykonać przywracanie i nie możemy, ponieważ inni użytkownicy są połączeni. Myśleliśmy, że odłączyliśmy każdy proces, ale najwyraźniej nie.
Jak możemy, z Management Studio, wykopać wszystkich innych, abyśmy mogli wykonać tę kopię zapasową?
Musimy wykonać przywracanie i nie możemy, ponieważ inni użytkownicy są połączeni. Myśleliśmy, że odłączyliśmy każdy proces, ale najwyraźniej nie.
Jak możemy, z Management Studio, wykopać wszystkich innych, abyśmy mogli wykonać tę kopię zapasową?
Odpowiedzi:
Można to zrobić na dwa sposoby:
Kliknij bazę danych prawym przyciskiem myszy w Eksploratorze obiektów i wybierz Zadania> Odłącz. Zaznacz pole wyboru Drop Connections.
Ustaw bazę danych w tryb pojedynczego użytkownika, jak opisano tutaj :
-- hit Ctrl+Shift+M in SSMS to fill in the template parameter
USE master;
GO
ALTER DATABASE N'<Database Name, sysname,>'
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
ALTER DATABASE N'<Database Name, sysname,>'
SET READ_ONLY;
GO
ALTER DATABASE N'<Database Name, sysname,>'
SET MULTI_USER;
GO
Zawsze używam następujących:
USE master; -- get out of dbname myself
GO
-- kick all other users out:
ALTER DATABASE [dbname] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
-- prevent sessions from re-establishing connection:
ALTER DATABASE [dbname] SET OFFLINE;
Czasami może to chwilę potrwać, a czasem jest blokowane, ponieważ to Ty go uruchamiasz i masz aktywne połączenie z bazą danych . Sprawdź inne okna zapytań, które mogą mieć ten sam kontekst bazy danych - może to obejmować otwarte okna dialogowe, Eksplorator obiektów, IntelliSense, długotrwałe zadania itp.
Kiedy skończę wprowadzać zmiany w konfiguracji tej bazy danych, po prostu:
ALTER DATABASE [dbname] SET ONLINE;
ALTER DATABASE [dbname] SET MULTI_USER;
Chociaż czasami rzeczą, którą muszę zrobić z tą bazą danych, jest jej potrzeba, aby baza była w trybie online, więc czasami muszę pozostawić ją w trybie pojedynczego użytkownika i zrobić to:
ALTER DATABASE [dbname] SET ONLINE;
GO
USE [dbname];
Teraz mogę wprowadzić zmiany, a kiedy będę gotowy na połączenie z innymi użytkownikami, po prostu:
ALTER DATABASE [dbname] SET MULTI_USER;
Zwykle ustawiam bazę danych w trybie single_user, a następnie czekam na opóźnienie, a następnie ustawiam bazę danych z powrotem dla wielu użytkowników, jak poniżej:
-- to kill all connections for particular db ... otherwise the restore will fail as exclusive lock cannot be obtained for the db being restored.
alter database db_name
set single_user with rollback immediate
waitfor delay '00:00:05' -- wait for 5 secs
alter database db_name
set multi_user
restore database db_name from disk = 'D:\restore\db_name.bak'
with replace, stats = 10, recovery -- if you want to recover your database online
-- optional if you dont have the same directory/file structure
move 'datafile logical name' to 'E:\data\physical_name.mdf',
move 'logfile logical name' to 'F:\log\physical_name_log.ldf'
Poniższe faktycznie zabija wszystkie połączenia. Całkiem przydatne w przypadkach, w których nie działa ustawienie trybu pojedynczego użytkownika
declare @execSql varchar(1000), @databaseName varchar(100)
-- Set the database name for which to kill the connections
set @databaseName = 'databasename'
set @execSql = ''
select @execSql = @execSql + 'kill ' + convert(char(10), spid) + ' '
from master.dbo.sysprocesses
where db_name(dbid) = @databaseName
and
DBID <> 0
and
spid <> @@spid
exec(@execSql)
sysprocesses
nie zawsze uwzględnia wszystkie sesje, które mogą zawierać blokady w tej bazie danych (pomyśl o prostym scenariuszu, w którym zapytanie jest uruchamiane w kontekście bazy danych A, ale dołącza do tabeli w A i tabeli w B) .
Możesz użyć poniższego skryptu, aby nuke wszystkich lub zmodyfikować dla konkretnej bazy danych.
Wszystko, co można zabić, będzie! Nie będzie to miało wpływu na identyfikatory SPID usługi SQL.
Drop table #who
go
Create table #who( [spid] int,
[ECID] int,
[Status] varchar(100),
[Loginname] varchar(200),
[Hostname] varchar(200),
[blk] bit,
dbname varchar(200),
cmd varchar(1000),
requestID int
)
go
Insert into #who (Spid, ECID, Status, Loginname, hostname,blk, dbname, cmd, requestid)
exec sp_who
Declare cursKillUsers Cursor for Select 'Kill ' + cast(spid as varchar(100)) + ';' [SQL] from #who where dbname like '%'
Declare @sql varchar(200)
Open cursKillUsers
Fetch next from cursKillUsers into @sql
While @@fetch_status = 0
begin
print @sql
Exec (@sql)
Fetch next from cursKillUsers into @sql
end
close cursKillUsers
deallocate cursKillUsers
Używam tego kodu:
ALTER DATABASE [Dbname] set offline with rollback immediate
GO
ALTER DATABASE [Dbname] set online
GO
Ale widzę, że przykład POJEDYNCZY UŻYTKOWNIK jest mniej do pisania.