คุณจะฆ่าการเชื่อมต่อปัจจุบันทั้งหมดไปยังฐานข้อมูล SQL Server 2005 ได้อย่างไร


288

ฉันต้องการเปลี่ยนชื่อฐานข้อมูล แต่ได้รับข้อผิดพลาดที่ 'ไม่สามารถล็อกแบบเอกสิทธิ์เฉพาะบุคคล' ในฐานข้อมูลซึ่งแสดงว่ามีการเชื่อมต่อบางส่วนยังคงทำงานอยู่

ฉันจะฆ่าการเชื่อมต่อทั้งหมดไปยังฐานข้อมูลเพื่อให้ฉันสามารถเปลี่ยนชื่อได้อย่างไร?

คำตอบ:


378

เหตุผลที่วิธีการที่อดัมแนะนำไม่ทำงานก็คือในช่วงเวลาที่คุณทำการวนรอบการเชื่อมต่อที่ใช้งานอยู่คุณสามารถสร้างการเชื่อมต่อใหม่และคุณจะพลาดสิ่งเหล่านั้น คุณสามารถใช้วิธีการต่อไปนี้แทนซึ่งไม่มีข้อเสีย:

-- 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
ดูเหมือนจะใช้งานไม่ได้กับ SQL Server 2008 ... นี่คือข้อผิดพลาดที่ฉันได้รับ: คอนโซล: ข่าวสารเกี่ยวกับ 102 ระดับ 15 สถานะ 1 บรรทัดที่ 4 ไวยากรณ์ที่ไม่ถูกต้องใกล้ '-' เกี่ยวกับข่าวสาร 319 ระดับ 15 สถานะ 1 บรรทัด 4 ไวยากรณ์ไม่ถูกต้องใกล้กับคำสำคัญ 'กับ' หากคำสั่งนี้เป็นนิพจน์ตารางทั่วไปส่วนคำสั่ง xmlnamespaces หรือส่วนคำสั่งการติดตามการเปลี่ยนแปลงคำสั่งก่อนหน้านี้จะต้องสิ้นสุดด้วยเครื่องหมายอัฒภาค ข่าวสารเกี่ยวกับ 102 ระดับ 15 สถานะ 1 บรรทัด 4 ไวยากรณ์ไม่ถูกต้องใกล้ 'IMMEDIATE' คำสั่ง: แก้ไขฐานข้อมูล ASMR-wdanda SET SINGLE_USER พร้อมย้อนกลับทันที
Wagner da Silva

ฉันเพิ่งทำงานนี้ในปี 2008 โดยไม่มีปัญหาแก้ไขฐานข้อมูล aspnetdb SET SINGLE_USER ด้วย ROLLBACK ทันทีเลือก GETDATE () แก้ไขฐานข้อมูล aspnetdb SETNET MULTI_USER สิ่งที่คุณมีแทนความคิดเห็นรหัส?
SQLMenace

ทำงานให้ฉันด้วย SQL Server 2008 และอินสแตนซ์ของ SQL Express
ทิมเมอร์ฟี

19
@ Wagner หากฐานข้อมูลมีเครื่องหมาย '-' ในชื่อที่คุณต้องใช้วงเล็บเหลี่ยม: ALTER DATABASE [foo-bar] SET SINGLE_USER พร้อม ROLLBACK ทันที
Ben Challenor

14
โปรดทราบ - อย่าลองสิ่งนี้บนเซิร์ฟเวอร์ SQL ที่โฮสต์บน Amazon RDS คุณจะไม่สามารถรีเซ็ต DB กลับไปที่โหมด MULTI_USER ตรวจสอบให้แน่ใจว่าคุณมีหนังสือรับรอง DBA อีกชุดหนึ่งก่อนที่จะลองทำ ฉันแก้ไขสิ่งนี้ด้วยการย้อนกลับเป็นหนึ่งในสแน็ปช็อตก่อนหน้า สูญเสียข้อมูลบางส่วน โชคดีที่ข้อมูลไม่สำคัญ
RuntimeException

110

สคริปต์เพื่อดำเนินการนี้ให้แทนที่ 'DB_NAME' ด้วยฐานข้อมูลเพื่อฆ่าการเชื่อมต่อทั้งหมดไปที่:

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
สิ่งนี้ใช้งานได้สำหรับฉันฉันเพิ่มลงand spid <> @@SPIDในSELECT @sKillConnectionคำสั่งเพื่อที่จะไม่พยายามฆ่าการเชื่อมต่อปัจจุบันของฉันซึ่งจะสร้างข้อความแสดงข้อผิดพลาด
Luis Perez

กระบวนการของผู้ใช้เท่านั้นที่สามารถฆ่าได้ ... ยังคงหยุดชะงักและไม่สามารถกู้คืนโหมด multi_user ได้เนื่องจากการหยุดชะงัก
rainabba

mateuscb- วิธีเดียวที่จะใช้ไม่ได้กับ mssql 10.00 คือถ้าคุณมีชื่อฐานข้อมูลที่ต้องการ [] และคุณไม่ได้ใช้ เปลี่ยนฐานข้อมูลของคุณ [YourDatabase] SET SINGLE_USER กับ ROLLBACK ทันทีทำงานใน 10, 10.5, 11 และ 12
Jeremy

ผู้ช่วยชีวิต ควรเป็นคำตอบที่ดีที่สุด
gls123

55

ฆ่ามันและฆ่ามันด้วยไฟ:

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:

ในทรี Object Explorer เจาะลึกภายใต้การจัดการเป็น "การตรวจสอบกิจกรรม" (หากคุณไม่พบที่นั่นแล้วคลิกขวาบนเซิร์ฟเวอร์ฐานข้อมูลและเลือก "การตรวจสอบกิจกรรม") เปิดการตรวจสอบกิจกรรมคุณสามารถดูข้อมูลกระบวนการทั้งหมด คุณควรจะสามารถค้นหาล็อคสำหรับฐานข้อมูลที่คุณสนใจและฆ่าล็อคเหล่านั้นซึ่งจะฆ่าการเชื่อมต่อ

คุณควรจะสามารถเปลี่ยนชื่อได้หลังจากนั้น


ฉันไม่เห็นรายการ "การตรวจสอบกิจกรรม" ภายใต้การจัดการ ... อาจเป็นเพราะฉันใช้ SQL 2008 อยู่ใช่ไหม
Wagner da Silva

14
ฉันพบ "กิจกรรม Montior" หากคุณคลิกขวาที่เซิร์ฟเวอร์ไม่ใช่ฐานข้อมูล จากนั้นคุณสามารถเลือกแท็บ 'กระบวนการ' และกรองตามฐานข้อมูล
alirobe

เห็นได้ชัดว่าคุณต้องฆ่ากระบวนการจนตรอกทีละคน แต่มันเป็นวิธีที่ตรงไปตรงมาที่ไม่จำเป็นต้องเข้าสู่ระบบท้องถิ่นหรือนำเซิร์ฟเวอร์ฐานข้อมูลที่สมบูรณ์ลง
ÁlvaroGonzález

24

ฉันเคยใช้:


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 


14

ใช้ออฟไลน์ใช้เวลาสักครู่และบางครั้งฉันประสบปัญหาบางอย่างกับที่ ..

วิธีที่แข็งแกร่งที่สุดในความคิดของฉัน:

แยกออก คลิกขวาที่ DB -> Tasks -> Detach ... ตรวจสอบ "Drop Connections" ตกลง

Reattach คลิกขวาที่ฐานข้อมูล -> แนบ .. เพิ่ม ... -> เลือกฐานข้อมูลของคุณแล้วเปลี่ยนคอลัมน์แนบเป็นชื่อฐานข้อมูลที่คุณต้องการ ตกลง


ชอบมัน. วิธีที่เร็วที่สุดในการทำจาก GUI อย่างแน่นอน
Whelkaholism

มันใช้งานได้เหมือนมีเสน่ห์! วิธีที่ง่ายคือวิธีที่ดี ขอบคุณ
ลากจูง

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

ใช้ฐานข้อมูล 'ต้นแบบ' และเรียกใช้แบบสอบถามนี้จะฆ่าการเชื่อมต่อที่ใช้งานทั้งหมดจากฐานข้อมูลของคุณ


1
มันใช้งานได้จริง :) ฉันอยากจะแนะนำว่าเพื่อให้ส่วนที่รันของสคริปต์นี้แสดงความคิดเห็นออกมาและใส่ print @query แทนเพื่อให้แน่ใจว่าคุณไม่ได้เรียกใช้สิ่งนี้บนเซิร์ฟเวอร์ที่ใช้งานจริงโดยไม่ได้ตั้งใจ
Marcello Miorelli

5

ฉันมักจะพบข้อผิดพลาดเมื่อฉันพยายามกู้คืนฐานข้อมูลฉันมักจะไปที่ด้านบนสุดของแผนภูมิใน Management Studio และคลิกขวาและรีสตาร์ทเซิร์ฟเวอร์ฐานข้อมูล (เพราะอยู่ในเครื่องพัฒนานี่อาจไม่เหมาะสำหรับการผลิต ) นี่เป็นการปิดการเชื่อมต่อฐานข้อมูลทั้งหมด


ขอบคุณนี้ใช้งานได้ ( ALTER DATABASE ... SET SINGLE_USERคำสั่งในคำตอบอื่น ๆ กลับข้อผิดพลาด 'ไม่สามารถล็อคแบบเอกสิทธิ์เฉพาะบุคคล' กลับคืนได้)
Tinister

4

ใน MS SQL Server Management Studio บนออบเจกต์ explorer ให้คลิกขวาที่ฐานข้อมูล ในเมนูบริบทที่ตามมาให้เลือก 'Tasks -> Take ออฟไลน์'


4
คุณไม่สามารถทำได้หากมีการเชื่อมต่อที่ใช้งานอยู่
alirobe

4

วิธี "ฆ่าด้วยไฟ" อีกวิธีหนึ่งคือเพียงแค่เริ่มบริการ MSSQLSERVER ใหม่ ฉันชอบทำสิ่งต่าง ๆ จาก commandline การวางสิ่งนี้ลงใน CMD จะทำเช่นนั้น: NET STOP MSSQLSERVER และ NET START MSSQLSERVER

หรือเปิด "services.msc" และค้นหา "SQL Server (MSSQLSERVER)" และคลิกขวาเลือก "เริ่มต้นใหม่"

สิ่งนี้จะ "แน่นอน" ฆ่าการเชื่อมต่อทั้งหมดไปยังฐานข้อมูลทั้งหมดที่ทำงานบนอินสแตนซ์นั้น

(ฉันชอบสิ่งนี้ดีกว่าวิธีการมากมายที่เปลี่ยนแปลงและเปลี่ยนกลับการกำหนดค่าบนเซิร์ฟเวอร์ / ฐานข้อมูล)


คุณหมายถึงอะไร 'ไม่แนะนำ' หากคุณไม่ได้กังวลเกี่ยวกับการเชื่อมต่อกับเซิร์ฟเวอร์นั้น (เช่น: สภาพแวดล้อมการดีบักหรือการจัดเตรียมเช่น - หรือเซิร์ฟเวอร์ที่ใช้งานจริงซึ่งมีอุณหภูมิหยุดทำงาน) นี่อาจเป็นวิธีที่ง่ายที่สุด สำหรับการผลิต - คุณไม่ต้องการที่จะล้อเล่นกับการกำหนดค่าหากคุณสามารถเริ่มบริการใหม่ได้ คุณจะทำอย่างไร
aikeru

1
ฉันจะไปเพื่ออะไรก็ตามที่ควรมีผลกับฐานข้อมูลเป้าหมายเท่านั้น วิธีการฆ่าฐานข้อมูลทั้งหมดของคุณบนเซิร์ฟเวอร์เป้าหมายไม่ใช่วิธีที่ฉลาด แต่พูดตามตรงในสภาพแวดล้อมการแสดงละครนี่อาจเป็นวิธีที่ง่ายที่สุดที่คุณพูด
Mohammed Swillam

4

ต่อไปนี้เป็นวิธีเชื่อถือได้ของประเภทนี้ใน MS SQL Server Management Studio 2008 (อาจใช้ได้กับรุ่นอื่นด้วย):

  1. ในทรี Object Explorer คลิกขวาที่เซิร์ฟเวอร์ฐานข้อมูลรูท (ด้วยลูกศรสีเขียว) จากนั้นคลิกมอนิเตอร์กิจกรรม
  2. เปิดแท็บกระบวนการในการตรวจสอบกิจกรรมเลือกเมนูแบบเลื่อนลง 'ฐานข้อมูล' และกรองตามฐานข้อมูลที่คุณต้องการ
  3. คลิกขวาที่ DB ใน Object Explorer และเริ่มงาน 'Tasks -> Take ออฟไลน์' ปล่อยให้สิ่งนี้ทำงานเป็นเบื้องหลังในขณะที่คุณ ...
  4. ปิดสิ่งที่คุณทำได้อย่างปลอดภัย
  5. ฆ่ากระบวนการที่เหลือทั้งหมดจากแท็บกระบวนการ
  6. นำ DB กลับมาออนไลน์
  7. เปลี่ยนชื่อฐานข้อมูล
  8. นำบริการของคุณกลับมาออนไลน์และชี้ไปที่ฐานข้อมูลใหม่

3

ตัวเลือกที่เหมาะกับฉันในสถานการณ์นี้เป็นดังนี้:

  1. เริ่มการทำงาน "แยก" ในฐานข้อมูลที่เป็นปัญหา สิ่งนี้จะเปิดหน้าต่าง (ใน SQL 2005) แสดงการเชื่อมต่อที่ใช้งานอยู่ซึ่งป้องกันการกระทำบนฐานข้อมูล
  2. ฆ่าการเชื่อมต่อที่ใช้งานอยู่ยกเลิกการดำเนินการแยกออก
  3. ฐานข้อมูลควรพร้อมใช้งานสำหรับการกู้คืนแล้ว

ใน SQL 2008 Management Studio คุณด้วยเหตุผลบางอย่างไม่สามารถเข้าถึงการเชื่อมต่อที่ใช้งานได้จากหน้าจอ "แยก" มันใช้งานได้ดีในปี 2005 และนี่คือวิธีที่ฉันทำไปเรื่อย ๆ จนกว่าเราจะอัปเกรดเป็น 2008 และตอนนี้สิ่งที่คุณได้รับคือข้อความโง่ ๆ ที่บอกให้คุณปิดการเชื่อมต่อ แต่ไม่อนุญาตให้คุณเปิดรายละเอียดการเชื่อมต่อ .
Jim


2

คลิกขวาที่ชื่อฐานข้อมูลคลิกที่คุณสมบัติเพื่อรับหน้าต่างคุณสมบัติเปิดแท็บตัวเลือกและเปลี่ยนคุณสมบัติ "จำกัด การเข้าถึง" จากผู้ใช้หลายคนเป็นผู้ใช้รายเดียว เมื่อคุณกดปุ่ม OK ระบบจะแจ้งให้คุณปิดการเชื่อมต่อที่เปิดอยู่ทั้งหมดเลือก "ใช่" และคุณได้รับการตั้งค่าให้เปลี่ยนชื่อฐานข้อมูล ....


2

สิ่งเหล่านี้ใช้ไม่ได้กับฉัน (SQL2008 Enterprise) ฉันไม่เห็นกระบวนการทำงานหรือผู้ใช้ที่เชื่อมต่อกับฐานข้อมูล การรีสตาร์ทเซิร์ฟเวอร์ (คลิกขวาบน Sql Server ใน Management Studio และเลือก Restart) อนุญาตให้ฉันกู้คืนฐานข้อมูล


2

ฉันใช้ SQL Server 2008 R2 ฐานข้อมูลของฉันถูกตั้งค่าไว้แล้วสำหรับผู้ใช้คนเดียวและมีการเชื่อมต่อที่ จำกัด การดำเนินการใด ๆ บนฐานข้อมูล ดังนั้นโซลูชันของ SQLMenace ที่แนะนำจึงตอบสนองด้วยข้อผิดพลาด นี่คือหนึ่งในที่ทำงานในกรณีของฉัน


0

ฉันใช้ sp_who เพื่อรับรายการกระบวนการทั้งหมดในฐานข้อมูล สิ่งนี้ดีกว่าเพราะคุณอาจต้องการตรวจสอบกระบวนการที่จะฆ่า

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

ผลลัพธ์
คุณสามารถใช้คำสั่งในคอลัมน์ KillCommand เพื่อฆ่ากระบวนการที่คุณต้องการ

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

-1

คุณสามารถใช้คำสั่ง SP_Who และฆ่ากระบวนการทั้งหมดที่ใช้ฐานข้อมูลของคุณแล้วเปลี่ยนชื่อฐานข้อมูลของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.