Làm thế nào để bạn giết tất cả các kết nối hiện tại đến cơ sở dữ liệu SQL Server 2005?


288

Tôi muốn đổi tên cơ sở dữ liệu, nhưng tiếp tục gặp lỗi 'không thể có khóa độc quyền' trên cơ sở dữ liệu, ngụ ý rằng có một số kết nối vẫn hoạt động.

Làm thế nào tôi có thể giết tất cả các kết nối đến cơ sở dữ liệu để tôi có thể đổi tên nó?

Câu trả lời:


378

Lý do mà cách tiếp cận mà Adam đề xuất sẽ không hiệu quả là trong thời gian bạn lặp lại các kết nối đang hoạt động, kết nối mới có thể được thiết lập và bạn sẽ bỏ lỡ những kết nối đó. Thay vào đó, bạn có thể sử dụng phương pháp sau không có nhược điểm này:

-- 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
Điều đó dường như không hoạt động đối với SQL Server 2008 ... Đây là lỗi tôi gặp phải: Bảng điều khiển: Msg 102, Cấp 15, Trạng thái 1, Dòng 4 Cú pháp không chính xác gần '-'. Msg 319, Cấp 15, Trạng thái 1, Dòng 4 Cú pháp không chính xác gần từ khóa 'với'. Nếu câu lệnh này là biểu thức bảng chung, mệnh đề xmlnamespaces hoặc mệnh đề ngữ cảnh theo dõi thay đổi, thì câu lệnh trước phải được chấm dứt bằng dấu chấm phẩy. Msg 102, Cấp 15, Trạng thái 1, Dòng 4 Cú pháp không chính xác gần 'NGAY LẬP TỨC'. Lệnh: ALTER DATABASE ASMR-wdanda SET SINGLE_USER VỚI ROLLBACK NGAY LẬP TỨC
Wagner da Silva

Tôi chỉ chạy cái này vào năm 2008 mà không gặp vấn đề ALTER DATABASE aspnetdb SET SINGLE_USER VỚI ROLLBACK NGAY LẬP TỨC chọn GETDATE () ALTER DATABASE aspnetdb SET MULTI_USER Bạn có gì thay vì mã nhận xét?
SQLMenace

Làm việc cho tôi với phiên bản SQL Server 2008 và SQL Express.
Tim Murphy

19
@Wagner nếu cơ sở dữ liệu có '-' trong tên bạn cần sử dụng dấu ngoặc quanh nó: ALTER DATABASE [foo-bar] SET SINGLE_USER VỚI ROLLBACK NGAY LẬP TỨC
Ben Challenor

14
Xin lưu ý - KHÔNG thử điều này trên Máy chủ SQL được lưu trữ trên Amazon RDS. Bạn sẽ không thể thiết lập lại DB về chế độ MULTI_USER. Hãy chắc chắn rằng bạn có một bộ thông tin DBA khác trước khi bạn thử điều này. Tôi đã sửa lỗi này bằng cách quay lại một trong các ảnh chụp nhanh trước đó. Mất một số dữ liệu. May mắn thay, dữ liệu không quan trọng.
RuntimeException

110

Tập lệnh để thực hiện việc này, thay thế 'DB_NAME' bằng cơ sở dữ liệu để hủy tất cả các kết nối tới:

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
Điều này làm việc cho tôi, tôi đã thêm and spid <> @@SPIDvào SELECT @sKillConnectiontuyên bố để nó không cố gắng giết kết nối hiện tại của tôi, điều này sẽ tạo ra một thông báo lỗi.
Luis Perez

Chỉ các tiến trình người dùng có thể bị giết ... vẫn bị bế tắc và không thể khôi phục chế độ multi_user do bế tắc.
rainabba

mateuscb - cách duy nhất nó không hoạt động trên mssql 10:00 là nếu bạn có tên cơ sở dữ liệu yêu cầu [] và bạn không sử dụng chúng. ALTER DATABASE [YourDatabase] SET SINGLE_USER VỚI ROLLBACK NGAY làm việc tại 10, 10.5, 11 và 12.
Jeremy

Phao cứu sinh. Nên là câu trả lời hàng đầu.
gls123

55

Giết nó và giết nó bằng lửa:

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

Sử dụng SQL Management Studio Express:

Trong cây Object Explorer, đi sâu vào phần Quản lý để "Trình giám sát hoạt động" (nếu bạn không thể tìm thấy nó ở đó thì nhấp chuột phải vào máy chủ cơ sở dữ liệu và chọn "Trình giám sát hoạt động"). Mở Trình giám sát hoạt động, bạn có thể xem tất cả thông tin về quy trình. Bạn sẽ có thể tìm thấy các khóa cho cơ sở dữ liệu mà bạn quan tâm và giết các khóa đó, điều này cũng sẽ giết kết nối.

Bạn sẽ có thể đổi tên sau đó.


Tôi không thấy mục "Trình giám sát hoạt động" này trong Quản lý ... Một lần nữa, có lẽ vì tôi đang sử dụng SQL 2008?
Wagner da Silva

14
Tôi đã tìm thấy "Hoạt động Montior" nếu bạn nhấp chuột phải vào SERVER, không phải DB. Sau đó, bạn có thể chọn tab 'Quy trình' và lọc theo Cơ sở dữ liệu.
alirobe

Bạn rõ ràng cần phải giết từng quá trình bị đình trệ nhưng đó là một phương pháp đơn giản không yêu cầu đăng nhập cục bộ hoặc đưa máy chủ cơ sở dữ liệu hoàn chỉnh xuống.
Álvaro González

24

Tôi đã luôn sử dụng:


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

Ngoại tuyến mất một lúc và đôi khi tôi gặp một số vấn đề với điều đó ..

Cách vững chắc nhất theo ý kiến ​​của tôi:

Detach Nhấp chuột phải vào DB -> Nhiệm vụ -> Detach ... kiểm tra "Thả kết nối" Ok

Reattach Nhấp chuột phải vào Cơ sở dữ liệu -> Đính kèm .. Thêm ... -> chọn cơ sở dữ liệu của bạn và thay đổi cột Đính kèm dưới dạng tên cơ sở dữ liệu bạn muốn. Đồng ý


Thích nó Cách nhanh nhất để làm điều đó từ GUI chắc chắn.
Whelkaholism

Nó hoạt động như một say mê! Cách dễ dàng là cách tốt. Cảm ơn.
Kéo mạnh

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

sử dụng cơ sở dữ liệu 'chính' và chạy truy vấn này, nó sẽ giết tất cả các kết nối hoạt động từ cơ sở dữ liệu của bạn.


1
Mặc dù vậy, nó thực sự hoạt động :) Tôi sẽ khuyên, để giữ phần thực thi của tập lệnh này được nhận xét và thay vào đó hãy in @query, để chắc chắn rằng bạn không chạy nhầm trên máy chủ sản xuất.
Marcello Miorelli

5

Tôi thường gặp phải lỗi đó khi tôi đang cố gắng khôi phục cơ sở dữ liệu Tôi thường chỉ đi đến ngọn cây trong Management Studio và nhấp chuột phải và khởi động lại máy chủ cơ sở dữ liệu (vì đó là trên máy phát triển, điều này có thể không lý tưởng trong sản xuất ). Đây là đóng tất cả các kết nối cơ sở dữ liệu.


Cảm ơn, điều này đã hoạt động (các ALTER DATABASE ... SET SINGLE_USERlệnh trong các câu trả lời khác trả về cùng một lỗi 'không thể nhận được khóa độc quyền').
Tinister

4

Trong MS SQL Server Management Studio trên trình thám hiểm đối tượng, nhấp chuột phải vào cơ sở dữ liệu. Trong menu ngữ cảnh theo sau, chọn 'Nhiệm vụ -> Ngoại tuyến'


4
Bạn không thể làm điều này nếu có kết nối hoạt động.
alirobe

4

Một cách tiếp cận "giết nó bằng lửa" là chỉ cần khởi động lại dịch vụ MSSQLSERVER. Tôi thích làm những thứ từ dòng lệnh. Dán chính xác điều này vào CMD sẽ thực hiện: NET STOP MSSQLSERVER & NET START MSSQLSERVER

Hoặc mở "services.msc" và tìm "SQL Server (MSSQLSERVER)" và nhấp chuột phải, chọn "khởi động lại".

Điều này sẽ "chắc chắn, chắc chắn" giết tất cả các kết nối đến TẤT CẢ các cơ sở dữ liệu đang chạy trên trường hợp đó.

(Tôi thích điều này tốt hơn nhiều cách tiếp cận thay đổi và thay đổi lại cấu hình trên máy chủ / cơ sở dữ liệu)


Ý bạn là 'không được đề xuất' là gì? Nếu bạn không quan tâm đến bất kỳ kết nối nào với máy chủ đó (ví dụ: môi trường gỡ lỗi hoặc dàn dựng - hoặc máy chủ sản xuất có thời gian ngừng hoạt động) thì đây có thể là cách dễ nhất. Đối với sản xuất - bạn không muốn làm hỏng cấu hình nếu bạn chỉ có thể khởi động lại dịch vụ. Bạn sẽ làm gì?
aikeru

1
Tôi sẽ đi cho bất cứ điều gì sẽ ảnh hưởng CHỈ DB mục tiêu của tôi. Cách tiếp cận của bạn để giết tất cả các DB trên máy chủ mục tiêu không phải là thông minh. nhưng thành thật mà nói, trong môi trường dàn dựng, đây có thể là cách dễ nhất như bạn đã nói.
Mohammed Swillam

4

Đây là cách đáng tin cậy loại điều này trong MS SQL Server Management Studio 2008 (cũng có thể hoạt động cho các phiên bản khác):

  1. Trong Object Explorer Tree, bấm chuột phải vào máy chủ cơ sở dữ liệu gốc (với mũi tên màu xanh lá cây), sau đó bấm vào màn hình hoạt động.
  2. Mở tab quy trình trong trình giám sát hoạt động, chọn menu thả xuống 'cơ sở dữ liệu và lọc theo cơ sở dữ liệu bạn muốn.
  3. Nhấp chuột phải vào DB trong Object Explorer và bắt đầu tác vụ 'Nhiệm vụ -> Thực hiện ngoại tuyến'. Để nó chạy trong nền trong khi bạn ...
  4. Tắt an toàn bất cứ điều gì bạn có thể.
  5. Giết tất cả các quy trình còn lại từ tab quy trình.
  6. Đưa DB trở lại trực tuyến.
  7. Đổi tên DB.
  8. Đưa dịch vụ của bạn trở lại trực tuyến và trỏ nó đến DB mới.

3

Tùy chọn làm việc cho tôi trong kịch bản này như sau:

  1. Bắt đầu hoạt động "Detach" trên cơ sở dữ liệu được đề cập. Điều này sẽ mở một cửa sổ (trong SQL 2005) hiển thị các kết nối hoạt động ngăn chặn các hành động trên DB.
  2. Giết các kết nối hoạt động, hủy bỏ hoạt động tách ra.
  3. Cơ sở dữ liệu nên có sẵn để khôi phục.

Trong SQL 2008 Management Studio, vì một số lý do, bạn không thể truy cập kết nối hoạt động từ màn hình "Tách". Nó hoạt động rất tốt vào năm 2005 và đây là cách tôi luôn làm, cho đến khi chúng tôi nâng cấp lên 2008 và bây giờ tất cả những gì bạn nhận được là một thông báo ngu ngốc bảo bạn đóng kết nối, nhưng không cho phép bạn mở chi tiết kết nối để giết từng kết nối .
Jim


2

Nhấp chuột phải vào tên cơ sở dữ liệu, nhấp vào Thuộc tính để nhận cửa sổ thuộc tính, Mở tab Tùy chọn và thay đổi thuộc tính "Hạn chế quyền truy cập" từ Nhiều người dùng thành Người dùng đơn. Khi bạn nhấn vào nút OK, nó sẽ nhắc bạn đóng tất cả kết nối đang mở, chọn "Có" và bạn được đặt để đổi tên cơ sở dữ liệu ....


2

Chúng không hoạt động với tôi (SQL2008 Enterprise), tôi cũng không thể thấy bất kỳ quy trình đang chạy hoặc người dùng nào được kết nối với DB. Khởi động lại máy chủ (Nhấp chuột phải vào Sql Server trong Management Studio và chọn Khởi động lại) cho phép tôi khôi phục DB.



0

Tôi sử dụng sp_who để lấy danh sách tất cả quá trình trong cơ sở dữ liệu. Điều này là tốt hơn bởi vì bạn có thể muốn xem lại quá trình để giết.

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

Kết quả
Bạn có thể sử dụng lệnh trong cột KillCommand để giết tiến trình bạn muốn.

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

-1

Bạn có thể sử dụng lệnh SP_Who và hủy tất cả quá trình sử dụng cơ sở dữ liệu của bạn và sau đó đổi tên cơ sở dữ liệu của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.