SQL Server 2005 veritabanına yapılan tüm bağlantıları nasıl öldürürsünüz?


288

Bir veritabanını yeniden adlandırmak istiyorum, ancak hala bazı bağlantı (lar) etkin olduğunu ima veritabanında 'özel kilit alınamadı' hatası almaya devam edin.

Yeniden adlandırabilmem için veritabanına olan tüm bağlantıları nasıl öldürebilirim?

Yanıtlar:


378

Adam'ın önerdiği yaklaşımın işe yaramamasının nedeni , aktif bağlantılar üzerinde döngü yaptığınız sırada yeni bir bağlantının kurulabileceği ve bunları kaçıracağınızdır. Bunun yerine, bu dezavantajı olmayan aşağıdaki yaklaşımı kullanabilirsiniz:

-- 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
Bu SQL Server 2008 için çalışmıyor gibi görünüyor ... İşte aldım hata: Konsol: Msg 102, Seviye 15, Durum 1, Hat 4 '-' yakınında yanlış sözdizimi. Msg 319, Seviye 15, Durum 1, Satır 4 'with' anahtar kelimesinin yanında yanlış sözdizimi. Bu ifade ortak bir tablo ifadesi, bir xmlnamespaces yan tümcesi veya değişiklik izleme bağlam yan tümcesi ise, önceki ifadenin noktalı virgülle sonlandırılması gerekir. Msg 102, Seviye 15, Durum 1, Satır 4 'HEMEN' yakınında yanlış sözdizimi. Komut: ALTER DATABASE ASMR-wdanda GERİ SIRA İLE SINGLE_USER SET
Wagner da Silva

Ben sadece 2008 yılında sorunsuz çalıştırdım ALTER DATABASE aspnetdb SET SINGLE_USER İLE ROLLBACK HEMEN seçin GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER yorum kodu dışında ne var?
SQLMenace

SQL Server 2008 ve SQL Express örneği ile çalıştı.
Tim Murphy

19
@Wagner, veritabanında adında bir '-' varsa etrafında parantez kullanmanız gerekir: ALTER DATABASE [foo-bar] SADECE TOPLAMA İLE SINGLE_USER SET
Ben Challenor

14
Lütfen Dikkat - Amazon RDS'de barındırılan SQL Server'da bunu DENEMEYİN. DB'yi MULTI_USER moduna sıfırlayamazsınız. Bunu denemeden önce başka bir DBA kimlik bilgileriniz olduğundan emin olun. Önceki görüntülerden birine dönerek bunu düzelttim. Bazı veriler kayboldu. Neyse ki veriler kritik değildi.
RuntimeException

110

Bunu yapmak için komut dosyası, tüm bağlantıları öldürmek için 'DB_NAME' veritabanını değiştirin:

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
Bu benim için çalıştı, ifadeye ekledim and spid <> @@SPID, SELECT @sKillConnectionböylece mevcut bağlantımı öldürmeye çalışmaz, bu da bir hata mesajı oluşturur.
Luis Perez

Yalnızca kullanıcı işlemleri öldürülebilir ... yine de kilitlenmemiş ve kilitlenme nedeniyle çok kullanıcılı modu geri yükleyemiyor.
rainabba

mateuscb- mssql 10.00 üzerinde çalışmayacak tek yol, [] gerektiren bir veritabanı adınız varsa ve bunları kullanmamanızdır. ALTER DATABASE [Veritabanınız] GERİ SIRA İLE SINGLE_USER SET 10, 10.5, 11 ve 12'de çalışır.
Jeremy

Cankurtaran. En iyi cevap olmalı.
gls123

55

Öldür ve ateşle öldür:

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

SQL Management Studio Express'i kullanma:

Nesne Gezgini ağacında "Etkinlik İzleyicisi" ne Yönetim altında ayrıntıya inin (orada bulamazsanız, veritabanı sunucusuna sağ tıklayın ve "Etkinlik İzleyicisi" ni seçin). Etkinlik Monitörü'nü açarak tüm işlem bilgilerini görüntüleyebilirsiniz. İlgilendiğiniz veritabanı için kilitleri bulabilmeniz ve bağlantıyı öldürecek olan kilitleri öldürebilmeniz gerekir.

Bundan sonra yeniden adlandırabilmelisin.


Yönetim altında bu "Etkinlik Monitörü" öğesini görmüyorum ... Yine, belki de SQL 2008 kullandığım için mi?
Wagner da Silva

14
DB değil, SUNUCU sağ tıklarsanız bir "Etkinlik Montior" buldum. Daha sonra 'İşlemler' sekmesini seçebilir ve Veritabanına göre filtreleyebilirsiniz.
Alirobe

Görünüşe göre durdurulmuş süreci tek tek öldürmeniz gerekiyor, ancak yerel giriş gerektirmeyen veya tüm veritabanı sunucusunu düşüren basit bir yöntem.
Álvaro González

24

Her zaman kullandım:


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

Çevrimdışı ol biraz zaman alıyor ve bazen bununla ilgili bazı sorunlar yaşıyorum.

Bence en sağlam yol:

Ayır Sağ Tıkla DB -> Görevler -> Ayır ... "Bağlantıları Bırak" ı işaretleyin Tamam

Reattach > takın .. ... Ekle - - Sağ Veritabanları tıklayın> veritabanını seçin ve istediğiniz veritabanı adının sütuna Olarak Ekle değiştirin. Tamam


Beğendim. Kesinlikle GUI'den bunu yapmanın en hızlı yolu.
Whelkaholism

Mucizevi şekilde çalışır! Kolay yol iyi yoldur. Teşekkürler.
Römorkör Güçlü

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

'ana' veritabanını kullanın ve bu sorguyu çalıştırın, veritabanınızdaki tüm etkin bağlantıları öldürür.


1
Gerçekten işe yarıyor :) Ancak, bu komut dosyasının yürütme kısmını yorumlu tutmak ve bunun yerine bir print @query koymak için, bunu yanlışlıkla bir üretim sunucusunda çalıştırmadığınızdan emin olmak için tavsiye ederim.
Marcello Miorelli

5

Genellikle bir veritabanını geri yüklemeye çalışırken bu hatayla karşılaşıyorum Genellikle Management Studio'daki ağacın en üstüne gider ve veritabanı sunucusunu sağ tıklatıp yeniden başlatırım (çünkü bir geliştirme makinesinde, bu üretimde ideal olmayabilir ). Bu, tüm veritabanı bağlantılarını kapatır.


Teşekkürler, bu çalıştı ( ALTER DATABASE ... SET SINGLE_USERdiğer cevaplardaki komutlar aynı 'özel kilit alınamadı' hatası döndürdü).
Tinister

4

Nesne gezginindeki MS SQL Server Management Studio'da veritabanına sağ tıklayın. Aşağıdaki bağlam menüsünde 'Görevler -> Çevrimdışına Al'ı seçin


4
Etkin bir bağlantı varsa bunu yapamazsınız.
Alirobe

4

Başka bir "ateşle öldür" yaklaşımı, MSSQLSERVER hizmetini yeniden başlatmaktır. Komut satırından bir şeyler yapmayı seviyorum. Bunu tam olarak CMD'ye yapıştırmak bunu yapacaktır: NET STOP MSSQLSERVER & NET START MSSQLSERVER

Veya "services.msc" dosyasını açın ve "SQL Server (MSSQLSERVER)" öğesini bulun ve sağ tıklayın, "yeniden başlat" ı seçin.

Bu, "kesin, kesin" o örnekte çalışan TÜM veritabanlarına TÜM bağlantıları kesecektir.

(Bunu sunucu / veritabanındaki yapılandırmayı değiştiren ve değiştiren birçok yaklaşımdan daha iyi seviyorum)


Ne demek 'tavsiye edilmiyor'? Bu sunucuya herhangi bir bağlantı (örneğin: hata ayıklama veya hazırlama ortamları, örneğin - veya geçici çalışmama süresine sahip bir üretim sunucusu) konusunda endişeleriniz yoksa, bu en kolay yol olabilir. Üretim için - hizmeti yeniden başlatabilirseniz, yapılandırma ile uğraşmak istemezsiniz. Sen ne yapardın?
aikeru

1
SADECE hedef DB etkilemesi gereken bir şey için gitmek istiyorum. hedef sunucudaki tüm DB'leri öldürme yaklaşımınız o kadar akıllı değil. ama dürüst olmak gerekirse, hazırlama ortamlarında, bu belki de dediğin gibi en kolay yol.
Mohammed Swillam

4

MS SQL Server Management Studio 2008'de bu tür şeylerin nasıl güvenilir bir şekilde yapılacağı aşağıda açıklanmıştır (diğer sürümler için de kullanılabilir):

  1. Nesne Gezgini Ağacı'nda, kök veritabanı sunucusunu (yeşil okla) sağ tıklatın, ardından etkinlik izleyicisini tıklatın.
  2. Etkinlik izleyicisinde işlemler sekmesini açın, 'veritabanları' açılır menüsünü seçin ve istediğiniz veritabanına göre filtreleyin.
  3. Nesne Gezgini'nde DB'yi sağ tıklayın ve 'Görevler -> Çevrimdışı Ol' görevini başlatın. Siz bunu yaparken arka planda çalışır halde bırakın ...
  4. Yapabildiğiniz her şeyi güvenle kapatın.
  5. İşlem sekmesinden kalan tüm işlemleri öldürün.
  6. DB'yi tekrar çevrimiçi duruma getirin.
  7. DB'yi yeniden adlandırın.
  8. Hizmetinizi tekrar çevrimiçi duruma getirin ve yeni DB'ye yönlendirin.

3

Bu senaryoda benim için çalışan seçenek aşağıdaki gibidir:

  1. Söz konusu veritabanında "Ayır" işlemini başlatın. Bu, DB üzerindeki eylemleri önleyen etkin bağlantıları gösteren bir pencere (SQL 2005'te) açar.
  2. Aktif bağlantıları öldürün, ayırma işlemini iptal edin.
  3. Veritabanı şimdi geri yüklenebilir durumda olmalıdır.

SQL 2008 Management Studio'da nedense "Ayır" ekranından etkin bağlantıya artık erişemezsiniz. 2005'te harika çalışıyor ve 2008'e yükseltme yapana kadar her zaman böyle yaptım ve şimdi tek yapmanız gereken bağlantınızı kapatmanızı söyleyen aptalca bir mesajdır, ancak her bağlantıyı öldürmek için bağlantı ayrıntılarını açmanıza izin vermez .
Jim


2

Veritabanı adına sağ tıklayın, özellik penceresini almak için Özellik'e tıklayın, Seçenekler sekmesini açın ve "Erişimi Kısıtla" özelliğini Çok Kullanıcıdan Tek Kullanıcıya değiştirin. Tamam düğmesine bastığınızda, tüm açık bağlantıyı kapatmanızı, "Evet" i seçmenizi ve veritabanını yeniden adlandırmayı seçmeniz istenir.


2

Bunlar benim için çalışmadı (SQL2008 Enterprise), ayrıca DB'ye bağlı çalışan herhangi bir işlem veya kullanıcı göremedim. Sunucuyu yeniden başlatmak (Management Studio'da Sql Server'a sağ tıklayın ve Yeniden Başlat'ı seçin) DB'yi geri yüklememe izin verdi.



0

Ben veritabanındaki tüm işlemlerin listesini almak için sp_who kullanın. Bu daha iyidir çünkü hangi işlemi öldüreceğinizi gözden geçirmek isteyebilirsiniz.

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

Sonuç
KillCommand sütununda, istediğiniz işlemi öldürmek için komutu kullanabilirsiniz.

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

-1

SP_Who komutunu kullanabilir ve veritabanınızı kullanan tüm işlemleri öldürebilir ve ardından veritabanınızı yeniden adlandırabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.