Bagaimana Anda membunuh semua koneksi saat ini ke database SQL Server 2005?

288

Saya ingin mengganti nama database, tetapi tetap mendapatkan kesalahan yang 'tidak bisa mendapatkan kunci eksklusif' pada database, yang menyiratkan ada beberapa koneksi yang masih aktif.

Bagaimana saya bisa mematikan semua koneksi ke database sehingga saya bisa mengganti nama?

Adam
sumber

Jawaban:

378

Alasan bahwa pendekatan yang disarankan Adam tidak akan berhasil adalah bahwa selama Anda mengulangi koneksi aktif yang baru dapat dibuat, dan Anda akan melewatkannya. Anda bisa menggunakan pendekatan berikut yang tidak memiliki kelemahan ini:

-- 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
SQLMenace
sumber
1
Itu tampaknya tidak berfungsi untuk SQL Server 2008 ... Berikut adalah kesalahan yang saya dapatkan: Console: Msg 102, Level 15, State 1, Line 4 Sintaks salah dekat '-'. Msg 319, Level 15, Negara 1, Baris 4 Sintaks salah di dekat kata kunci 'with'. Jika pernyataan ini adalah ekspresi tabel umum, klausa xmlnamespaces atau klausa konteks pelacakan perubahan, pernyataan sebelumnya harus diakhiri dengan tanda titik koma. Msg 102, Level 15, Negara 1, Baris 4 Sintaks salah dekat 'SEGERA'. Command: ALTER DATABASE ASMR-wdanda SET SINGLE_USER DENGAN ROLLBACK SEGERA
Wagner da Silva
Saya baru saja menjalankan ini pada 2008 tanpa masalah ALTER DATABASE aspnetdb SET SINGLE_USER DENGAN ROLLBACK SEGERA pilih GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER apa yang Anda miliki alih-alih kode yang dikomentari?
SQLMenace
Bekerja untuk saya dengan contoh SQL Server 2008 dan SQL Express.
Tim Murphy
19
@ Wagner jika databasenya memiliki '-' dalam nama yang Anda perlukan untuk menggunakan tanda kurung di sekitarnya: ALTER DATABASE [foo-bar] SET SINGLE_USER DENGAN ROLLBACK SEGERA
Ben Challenor
14
Perhatian - JANGAN coba ini di SQL Server yang dihosting di Amazon RDS. Anda tidak dapat mengatur ulang DB kembali ke mode MULTI_USER. Pastikan Anda memiliki set kredensial DBA lain sebelum Anda mencoba ini. Saya memperbaikinya dengan kembali ke salah satu foto sebelumnya. Kehilangan beberapa data. Untungnya datanya tidak kritis.
RuntimeException
110

Skrip untuk menyelesaikan ini, ganti 'DB_NAME' dengan database untuk mematikan semua koneksi ke:

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
Adam
sumber
1
Ini bekerja untuk saya, saya menambahkan and spid <> @@SPIDuntuk SELECT @sKillConnectionpernyataan sehingga tidak akan mencoba untuk membunuh koneksi saya saat ini, yang akan menghasilkan pesan kesalahan.
Luis Perez
Hanya proses pengguna yang dapat dimatikan ... masih menemui jalan buntu dan tidak dapat mengembalikan mode multi_user karena jalan buntu.
rainabba
mateuscb- satu-satunya cara itu tidak akan berfungsi pada mssql 10.00 adalah jika Anda memiliki nama database yang memerlukan [] dan Anda tidak menggunakannya. ALTER DATABASE [YourDatabase] SET SINGLE_USER DENGAN ROLLBACK SEGERA bekerja di 10, 10.5, 11 dan 12.
Jeremy
Penyelamat. Harus menjadi jawaban teratas.
gls123
55

Bunuh, dan bunuh dengan api:

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
btk
sumber
27

Menggunakan SQL Management Studio Express:

Di pohon Object Explorer telusuri bawah Manajemen untuk "Monitor Aktivitas" (jika Anda tidak dapat menemukannya di sana kemudian klik kanan pada server database dan pilih "Monitor Aktivitas"). Membuka Monitor Aktivitas, Anda dapat melihat semua info proses. Anda harus dapat menemukan kunci untuk basis data yang Anda minati dan mematikan kunci itu, yang juga akan mematikan koneksi.

Anda harus dapat mengganti nama setelah itu.

Joseph Daigle
sumber
Saya tidak melihat item "Monitor Aktivitas" ini di bawah Manajemen ... Sekali lagi, mungkin karena saya menggunakan SQL 2008?
Wagner da Silva
14
Saya telah menemukan "Activity Montior" jika Anda mengklik kanan SERVER, bukan DB. Anda kemudian dapat memilih tab 'Proses' dan memfilter menurut Database.
alirobe
Anda tampaknya perlu mematikan proses yang terhenti satu per satu, tetapi ini adalah metode langsung yang tidak memerlukan login lokal atau menjatuhkan server database lengkap.
Álvaro González
24

Saya selalu menggunakan:


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 
brendan
sumber
21
ALTER DATABASE [Test]
SET OFFLINE WITH ROLLBACK IMMEDIATE

ALTER DATABASE [Test]
SET ONLINE
santhosh kumar
sumber
14

Mengambil offline membutuhkan waktu dan kadang-kadang saya mengalami beberapa masalah dengan itu ..

Cara paling solid menurut saya:

Melepaskan Klik kanan DB -> Tugas -> Lepaskan ... centang "Drop Connections" Ok

Pasang kembali Klik kanan Database -> Lampirkan .. Tambah ... -> pilih basis data Anda, dan ubah kolom Lampirkan Sebagai ke nama basis data yang Anda inginkan. Baik

NJV
sumber
Suka itu. Cara tercepat untuk melakukannya dari GUI pasti.
Whelkaholism
Itu bekerja seperti pesona! Cara mudah adalah cara yang baik. Terima kasih.
Tarik kuat
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

gunakan database 'master' dan jalankan query ini, itu akan mematikan semua koneksi aktif dari database Anda.

Talha
sumber
1
Ini benar-benar berfungsi :) Saya akan menyarankan, untuk tetap menjalankan bagian dari skrip ini dikomentari dan meletakkan print @query sebagai gantinya, hanya untuk memastikan Anda tidak menjalankan ini pada server produksi karena kesalahan.
Marcello Miorelli
5

Saya biasanya mengalami kesalahan itu ketika saya mencoba mengembalikan database saya biasanya hanya pergi ke atas pohon di Management Studio dan klik kanan dan restart server database (karena itu pada mesin pengembangan, ini mungkin tidak ideal dalam produksi ). Ini menutup semua koneksi basis data.

RedWolves
sumber
Terima kasih, ini berhasil ( ALTER DATABASE ... SET SINGLE_USERperintah dalam jawaban lain mengembalikan kesalahan yang sama 'tidak bisa mendapatkan kunci eksklusif').
Tinister
4

Di MS SQL Server Management Studio pada objek explorer, klik kanan pada database. Di menu konteks yang mengikuti, pilih 'Tugas -> Ambil Offline'

John Christensen
sumber
4
Anda tidak dapat melakukan ini jika ada koneksi aktif.
alirobe
4

Pendekatan "bunuh dengan api" yang lain adalah dengan memulai kembali layanan MSSQLSERVER. Saya suka melakukan hal-hal dari commandline. Menempelkan ini ke CMD akan melakukannya: NET STOP MSSQLSERVER & NET START MSSQLSERVER

Atau buka "services.msc" dan cari "SQL Server (MSSQLSERVER)" dan klik kanan, pilih "restart".

Ini akan "pasti, pasti" membunuh SEMUA koneksi ke SEMUA database yang berjalan pada contoh itu.

(Saya suka ini lebih baik daripada banyak pendekatan yang mengubah dan mengubah kembali konfigurasi pada server / database)

aikeru
sumber
Apa maksudmu 'tidak direkomendasikan'? Jika Anda tidak khawatir tentang koneksi apa pun ke server itu (misalnya: debug atau lingkungan pementasan, misalnya - atau server produksi dengan downtime temp), ini mungkin cara termudah. Untuk produksi - Anda tidak ingin menjadi mucking dengan konfigurasi jika Anda bisa memulai kembali layanan. Apa yang akan kamu lakukan?
aikeru
1
Saya akan pergi untuk apa pun yang seharusnya mempengaruhi HANYA target DB saya. pendekatan Anda untuk membunuh semua DB di server target tidak sepintar itu. tapi jujur, dalam lingkungan pementasan, ini mungkin cara termudah seperti yang Anda katakan.
Mohammed Swillam
4

Inilah cara andal hal semacam ini di MS SQL Server Management Studio 2008 (dapat juga digunakan untuk versi lain):

  1. Di Pohon Object Explorer, klik kanan server basis data root (dengan panah hijau), lalu klik monitor aktivitas.
  2. Buka tab proses di monitor aktivitas, pilih menu drop-down 'database', dan filter berdasarkan database yang Anda inginkan.
  3. Klik kanan DB di Object Explorer dan mulai tugas 'Tugas -> Ambil Offline'. Biarkan ini berjalan di latar belakang saat Anda ...
  4. Tutup dengan aman apa pun yang Anda bisa.
  5. Bunuh semua proses yang tersisa dari tab proses.
  6. Bawa DB kembali online.
  7. Ganti nama DB.
  8. Bawa layanan Anda kembali online dan arahkan ke DB yang baru.
alirobe
sumber
3

Opsi yang berfungsi untuk saya dalam skenario ini adalah sebagai berikut:

  1. Mulai operasi "Lepaskan" pada database yang dimaksud. Ini akan membuka jendela (dalam SQL 2005) menampilkan koneksi aktif yang mencegah tindakan pada DB.
  2. Matikan koneksi yang aktif, batalkan operasi detasenya.
  3. Basis data sekarang harus tersedia untuk dipulihkan.
Lars Timenes
sumber
Di SQL 2008 Management Studio, Anda karena suatu alasan tidak dapat lagi mengakses koneksi aktif dari layar "Lepaskan". Ini berfungsi dengan baik pada tahun 2005 dan ini adalah bagaimana saya selalu melakukannya, sampai kami meningkatkan ke 2008 dan sekarang semua yang Anda dapatkan adalah pesan bodoh yang memberitahu Anda untuk menutup koneksi Anda, tetapi jangan biarkan Anda membuka detail koneksi untuk membunuh setiap koneksi .
Jim
2

Coba ini:

ALTER DATABASE [DATABASE_NAME]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
Joseph Sturtevant
sumber
2

Klik kanan pada nama database, klik Properti untuk mendapatkan jendela properti, Buka tab Opsi dan ubah properti "Batasi Akses" dari Multi Pengguna ke Pengguna Tunggal. Ketika Anda menekan tombol OK, itu akan meminta Anda untuk menutup semua koneksi yang terbuka, pilih "Ya" dan Anda ditetapkan untuk mengubah nama basis data ....

Sanjay Saxena
sumber
2

Ini tidak bekerja untuk saya (SQL2008 Enterprise), saya juga tidak bisa melihat proses yang berjalan atau pengguna yang terhubung ke DB. Restart server (Klik kanan pada Sql Server di Management Studio dan pilih Restart) memungkinkan saya untuk mengembalikan DB.

Sang Coder
sumber
0

Saya menggunakan sp_who untuk mendapatkan daftar semua proses dalam database. Ini lebih baik karena Anda mungkin ingin meninjau proses untuk membunuh yang mana.

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

Hasil
Anda dapat menggunakan perintah di kolom KillCommand untuk mematikan proses yang Anda inginkan.

SPID    KillCommand
26      kill 26;
27      kill 27;
28      kill 28;
Rawitas Krungkaew
sumber
-1

Anda dapat menggunakan perintah SP_Who dan membunuh semua proses yang menggunakan database Anda dan kemudian mengubah nama database Anda.

mehdi lotfi
sumber