একটি ডাটাবেসে সমস্ত সংযোগকে মেরে ফেলার স্ক্রিপ্ট (RESTRICTED_USER রোলব্যাকের চেয়ে বেশি)


239

আমার কাছে একটি ডেভেলপমেন্ট ডাটাবেস রয়েছে যা একটি ভিজ্যুয়াল স্টুডিও ডাটাবেস প্রকল্প (টিএফএস অটো বিল্ডের মাধ্যমে) থেকে প্রায়শই পুনঃ-মোতায়েন করে।

কখনও কখনও আমি আমার বিল্ড চালানোর সময় আমি এই ত্রুটিটি পাই:

ALTER DATABASE failed because a lock could not be placed on database 'MyDB'. Try again later.  
ALTER DATABASE statement failed.  
Cannot drop database "MyDB" because it is currently in use.  

আমি এটি চেষ্টা করেছি:

ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE

তবে আমি এখনও ডাটাবেস ড্রপ করতে পারি না। (আমার অনুমান যে বেশিরভাগ বিকাশকারীদের আছেdbo অ্যাক্সেস রয়েছে))

আমি নিজে চালাতে পারি SP_WHO এবং সংযোগগুলি হত্যা শুরু করতে পারি তবে অটো বিল্ডে এটি করার জন্য আমার একটি স্বয়ংক্রিয় উপায় প্রয়োজন। (যদিও এবার আমার সংযোগটি সেই ডিবিতে আমি একমাত্র ড্রপ করার চেষ্টা করছি))

এমন কোনও লিপি আছে যা আমার সাথে সংযুক্ত কিনা তা বিবেচনা না করেই ডাটাবেস ফেলে দিতে পারে?

উত্তর:


642

আপডেট করা হয়েছে

এমএস এসকিউএল সার্ভার ২০১২ এবং তারপরের জন্য

USE [master];

DECLARE @kill varchar(8000) = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), session_id) + ';'  
FROM sys.dm_exec_sessions
WHERE database_id  = db_id('MyDB')

EXEC(@kill);

এমএস এসকিউএল সার্ভার 2000, 2005, 2008 এর জন্য

USE master;

DECLARE @kill varchar(8000); SET @kill = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), spid) + ';'  
FROM master..sysprocesses  
WHERE dbid = db_id('MyDB')

EXEC(@kill); 

25
এটিই দুজনের উত্তম উত্তর; ডেটাবেস অফলাইনে নেওয়া এড়ানো এবং গ্রহণযোগ্য উত্তর সর্বদা কাজ করে না (কখনও কখনও এটি সমস্ত কিছু পিছিয়ে দিতে পারে না)।
মার্ক হেন্ডারসন

3
killসমস্ত একসাথে বিবৃতি একত্রিত করার জন্য যেমন একটি দুর্দান্ত উত্তর । আমি প্রতিটি প্রক্রিয়া হত্যা করার জন্য একটি কার্সার ব্যবহার করব, যা অবশ্যই কার্যকর নয়। এই উত্তরে ব্যবহৃত কৌশলটি উজ্জ্বল।
সা Saeedদ নেমতি

আমি মার্কের সাথে একমত এই পদ্ধতিটি গ্রহণযোগ্য উত্তর হওয়া উচিত কারণ এটি ডেটাবেসগুলির জন্য উল্লেখযোগ্যভাবে আরও মার্জিত এবং কম প্রভাবিত করে।
অস্টিন এস

3
ভাল এক এবং দ্রুত কেবল সিস্টেম স্পিডই সমস্যা হতে পারে তাই আপনি WHERE dbid = db_id ('My_db') যোগ করতে পারেন এবং স্পাইড> 50
সৌরভ সিনহা

1
@ ফ্রেঙ্কিবি রান স্ক্রিপ্টের আগে আপনাকে ডাটাবেস প্রসঙ্গে পরিবর্তন করতে হবে। প্রাক্তন হিসাবে:USE [Master]
আলেকস

133
USE master
GO
ALTER DATABASE database_name
SET OFFLINE WITH ROLLBACK IMMEDIATE
GO

রেফারেন্স: http://msdn.microid.com/en-us/library/bb522682%28v=sql.105%29.aspx


9
অদ্ভুতভাবে যথেষ্ট ছিল USE masterএটি ছিল মূল বিষয়। আমি db এর সাথে সংযোগের সময় ফেলে দেওয়ার চেষ্টা করছিলাম (ডু!)। ধন্যবাদ!
ভ্যাকাকানো

9
আপনি যদি ব্যবহার করেন তবে SET OFFLINEআপনাকে ডিবি ফাইল ম্যানুয়ালি মুছে ফেলতে হবে।
mattalxndr

5
alter database YourDatabaseName set SINGLE_USER with rollback immediateভাল হবে না ? আপনি যদি এটি সেট করেন OFFLINE(@ ম্যাটালেক্সেন্ডার হিসাবে বলা হয়েছে) ফাইলগুলি ডিস্কে ছেড়ে যাবে, তবে SINGLE_USERআপনার সংযোগটি কেবলমাত্র এক হিসাবে drop database YourDatabaseNameথাকবে এবং এখনও ফাইলগুলি সরিয়ে ফেলবে।
কিথ

1
স্ক্রিপ্টের কীথ, আপনি ডিবি-র সাথে সংযুক্ত নন, সুতরাং এটি "আপনার সংযোগ" নয়, তবে বাকি কিছু থাকবে। অবিলম্বে set offline, set onlineঅবশিষ্ট ফাইলগুলির সমস্যা এড়াতে আপনি ইস্যু করতে পারেন (হ্যাঁ, রেসের শর্তের সম্ভাবনা রয়েছে)।
ivan_pozdeev

2
ধন্যবাদ! আমি বুঝতে পারিনি যে এসকিউএল ম্যানেজমেন্ট স্টুডিওতে স্ক্যালি স্টেটমেন্ট সহ কিছু ট্যাব, এই ডেটাবেজে আগে মৃত্যুদন্ড কার্যকর করা হয়েছিল, আমার ডিবি ব্যবহারের জন্য রিপোর্ট করা হয়েছিল। মাস্টার ব্যবহার করুন, এবং যান, সবকিছু তৈরি করেছেন!
এথোর্ট

26

নিম্নলিখিতটি করে আপনি এসএসএমএস সরবরাহ করে এমন স্ক্রিপ্টটি পেতে পারেন:

  1. এসএসএমএসে একটি ডাটাবেসে ডান ক্লিক করুন এবং মুছুন পছন্দ করুন
  2. কথোপকথনে, "বিদ্যমান সংযোগগুলি বন্ধ করুন" এর জন্য চেকবক্সটি চেক করুন।
  3. কথোপকথনের শীর্ষে স্ক্রিপ্ট বোতামটি ক্লিক করুন।

স্ক্রিপ্টটি এরকম কিছু দেখবে:

USE [master]
GO
ALTER DATABASE [YourDatabaseName] SET  SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
USE [master]
GO
DROP DATABASE [YourDatabaseName]
GO

3
আমি কোনও ব্যবহারকারীর জন্য একক ব্যবহারকারী মোডে ডেটাবস নেওয়ার পরামর্শ দেব না কারণ এটি আপনাকে কিছু অ্যাপ্লিকেশন ব্যবহারকারীর সাথে বর্তমান সংযোগ আলগা করে দিতে পারে এবং সেই ব্যবহারকারীদের সন্ধান করতে এবং একইরকম বা কয়েকবার মেরে ফেলতে পারে যদি আপনি ডিবিতে সংযোগ থাকে তবে আপনাকে এসকিএল সার্ভার পুনরায় চালু করতে হবে u তাই ঘন ঘন।
সৌরভ সিনহা

7

অল্প পরিচিত: জিও স্কুয়েল বিবৃতি আগের কমান্ডটির পুনরাবৃত্তি করতে সংখ্যার জন্য একটি পূর্ণসংখ্যার নিতে পারে।

তাই যদি আপনি:

ALTER DATABASE [DATABASENAME] SET SINGLE_USER
GO

তারপর:

USE [DATABASENAME]
GO 2000

এটি ইউএসই কমান্ডকে 2000 বার পুনরাবৃত্তি করবে, অন্যান্য সমস্ত সংযোগে অচলাবস্থা জোর করে এবং একক সংযোগের মালিকানা গ্রহণ করবে। (আপনার ক্যোয়ারী উইন্ডোটিকে আপনার ইচ্ছামতো করতে একা অ্যাক্সেস দেওয়া))


2
জিও কোনও টিএসকিউএল কমান্ড নয় বরং একটি বিশেষ কমান্ড যা কেবল sqlcmd এবং osql ইউটিলিটি এবং এসএসএমএস দ্বারা স্বীকৃত।
ডাইসলেস

4

আমার অভিজ্ঞতার সাথে, SINGLE_USER ব্যবহার করা বেশিরভাগ সময় সাহায্য করে তবে একটি সতর্কতা অবলম্বন করা উচিত: আমি এমন একটি অনুষ্ঠানের অভিজ্ঞতা পেয়েছি যার মধ্যে আমি SINGLE_USER কমান্ড শুরু করার সময় এবং এটি শেষ হওয়ার সময়কালের মধ্যে ... সম্ভবত অন্য একজন 'ব্যবহারকারী' অর্জন করেছিল SINGLE_USER অ্যাক্সেস, আমি না। যদি এটি ঘটে থাকে, আপনি ডাটাবেসে ফিরে যাওয়ার অ্যাক্সেস পাওয়ার জন্য কঠোর কাজ করার চেষ্টা করছেন (আমার ক্ষেত্রে এটি এসকিউএল ডেটাবেসযুক্ত একটি সফ্টওয়্যারটির জন্য চলমান একটি নির্দিষ্ট পরিষেবা ছিল যা আমার করার আগেই SINGLE_USER অ্যাক্সেস ধরেছিল)। আমার মনে হয় যা সবচেয়ে নির্ভরযোগ্য উপায় হওয়া উচিত (এটির জন্য কোনও প্রমাণ দেওয়া যায় না, তবে আগামী দিনের মধ্যে এটিই আমি পরীক্ষা করব), আসলে:
- এমন পরিষেবাগুলি বন্ধ করুন যা আপনার অ্যাক্সেসে বাধা সৃষ্টি করতে পারে (যদি থাকে তবে)
- সমস্ত সংযোগ বন্ধ করতে উপরের 'কিল' স্ক্রিপ্টটি ব্যবহার করুন
- এর পরপরই সিঙ্গল_উসারে ডাটাবেস সেট করুন
- তারপরে পুনরুদ্ধার করুন


যদি SINGLE_USER কমান্ডটি আপনার (স্ক্রিপ্ট) পুনরুদ্ধার কমান্ডের একই ব্যাচে থাকে - জিও বিবৃতি দ্বারা পৃথক নয়! - তাহলে আমার অভিজ্ঞতা হিসাবে অন্য কোনও প্রক্রিয়া একক ব্যবহারকারীর অ্যাক্সেস গ্রহন করতে পারে না। যাইহোক, আমি আজ রাতে ধরা পড়েছিলাম কারণ আমার রাত্রে নির্ধারিত সেটটি একক ব্যবহারকারী; পুনরুদ্ধার; সেট-মাল্টি-ব্যবহারকারীর ব্লু আপ হয়েছিল। অন্য একটি প্রক্রিয়াতে আমার বক ফাইল (এসএমএইচ) এ একচেটিয়া ফাইল অ্যাক্সেস ছিল এবং সেহেতু পুনরুদ্ধার ব্যর্থ হয়েছিল, তারপরে এসইটি মাল্টি_উসার ব্যর্থ হচ্ছিল ... এর অর্থ যখন রক্তের জন্য মধ্যরাতে ডেকেছিলাম তখন অন্য কারও কাছে সিঙ্গেল_উসার অ্যাক্সেস ছিল এবং হত্যা করতে হয়েছিল।
রস প্রেসার

3

অবহেলিত সিস্টেমপ্রসেস সিস্টেম টেবিলটি প্রতিস্থাপন করে dm_exec_sessions DMV ব্যবহার করার জন্য ম্যাথিউয়ের সর্বোচ্চ দক্ষ স্ক্রিপ্ট আপডেট হয়েছে:

USE [master];
GO

DECLARE @Kill VARCHAR(8000) = '';

SELECT
    @Kill = @Kill + 'kill ' + CONVERT(VARCHAR(5), session_id) + ';'
FROM
    sys.dm_exec_sessions
WHERE
    database_id = DB_ID('<YourDB>');

EXEC sys.sp_executesql @Kill;

WHILE লুপ ব্যবহার করে বিকল্প (আপনি যদি মৃত্যুদণ্ড কার্যকর করে অন্য কোনও ক্রিয়াকলাপ প্রসেস করতে চান):

USE [master];
GO

DECLARE @DatabaseID SMALLINT = DB_ID(N'<YourDB>');    
DECLARE @SQL NVARCHAR(10);

WHILE EXISTS ( SELECT
                1
               FROM
                sys.dm_exec_sessions
               WHERE
                database_id = @DatabaseID )    
    BEGIN;
        SET @SQL = (
                    SELECT TOP 1
                        N'kill ' + CAST(session_id AS NVARCHAR(5)) + ';'
                    FROM
                        sys.dm_exec_sessions
                    WHERE
                        database_id = @DatabaseID
                   );
        EXEC sys.sp_executesql @SQL;
    END;

2

গৃহীত উত্তরের একটি অপূর্ণতা রয়েছে যে এটি বিবেচনায় নেবে না যে কোনও সংযোগের মাধ্যমে একটি ডাটাবেস লক করা যেতে পারে যা কোনও ক্যোয়ারী চালাচ্ছে যা সংযুক্ত হওয়া ব্যতীত অন্য কোনও ডাটাবেসে সারণী জড়িত করে।

এটি ক্ষেত্রে হতে পারে যদি সার্ভারের উদাহরণে একাধিক ডাটাবেস থাকে এবং ক্যোয়ারী প্রত্যক্ষ বা পরোক্ষভাবে (উদাহরণস্বরূপ প্রতিশব্দ মাধ্যমে) একাধিক ডাটাবেসে টেবিল ব্যবহার করে ইত্যাদি be

তাই আমি দেখতে পাই যে কখনও কখনও হত্যার সংযোগগুলি খুঁজে পেতে সিসলকিনফো ব্যবহার করা ভাল।

আমার পরামর্শ তাই অ্যালেক্সকে থেকে গৃহীত উত্তরের নীচের প্রকরণটি ব্যবহার করা হবে:

USE [master];

DECLARE @kill varchar(8000) = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), req_spid) + ';'  
FROM master.dbo.syslockinfo
WHERE rsc_type = 2
AND rsc_dbid  = db_id('MyDB')

EXEC(@kill);

এই! যদিও আমি ব্যক্তিগতভাবে sys.dm_tran_locksটেবিলটি syslockinfoঅপ্রচলিত হিসাবে চিহ্নিত হিসাবে চিহ্নিত করি, এছাড়াও, আপনি কেবলমাত্র বর্তমান ক্ষেত্রে এসপিআইডি বাদ দিতে চাইতে পারেন।
ডার্বি

1

হত্যা প্রক্রিয়া চলাকালীন ব্যতিক্রম সম্পর্কে আপনার যত্নবান হওয়া উচিত। সুতরাং আপনি এই স্ক্রিপ্টটি ব্যবহার করতে পারেন:

USE master;
GO
 DECLARE @kill varchar(max) = '';
 SELECT @kill = @kill + 'BEGIN TRY KILL ' + CONVERT(varchar(5), spid) + ';' + ' END TRY BEGIN CATCH END CATCH ;' FROM master..sysprocesses 
EXEC (@kill)

1

@ অ্যালেক্সেকে একটি দুর্দান্ত উত্তর লিখেছিল । আমি কেবল আমার দুটি সেন্ট যুক্ত করতে চাই। নীচের কোডটি পুরোপুরি @ অ্যালেক্সের উত্তরের উপর ভিত্তি করে, পার্থক্যটি হল আপনি শেষ ব্যাচটি কার্যকর হওয়ার পর থেকে ব্যবহারকারী এবং সময় উল্লেখ করতে পারেন (নোটটি মাস্টার..সাইসপ্রসেসের পরিবর্তে sys.dm_exec_sessions ব্যবহার করে):

DECLARE @kill varchar(8000);
set @kill =''
select @kill = @kill + 'kill ' +  CONVERT(varchar(5), session_id) + ';' from sys.dm_exec_sessions 
where login_name = 'usrDBTest'
and datediff(hh,login_time,getdate()) > 1
--and session_id in (311,266)    
exec(@kill)

এই উদাহরণে কেবলমাত্র ইউএসআরডিবিস্টেস্টের প্রক্রিয়াটি যা শেষ ব্যাচটি 1 ঘন্টারও বেশি সময় আগে কার্যকর হয়েছিল তা হত্যা করা হবে।


1

আপনি এর মতো কার্সার ব্যবহার করতে পারেন :

USE master
GO

DECLARE @SQL AS VARCHAR(255)
DECLARE @SPID AS SMALLINT
DECLARE @Database AS VARCHAR(500)
SET @Database = 'AdventureWorks2016CTP3'

DECLARE Murderer CURSOR FOR
SELECT spid FROM sys.sysprocesses WHERE DB_NAME(dbid) = @Database

OPEN Murderer

FETCH NEXT FROM Murderer INTO @SPID
WHILE @@FETCH_STATUS = 0

    BEGIN
    SET @SQL = 'Kill ' + CAST(@SPID AS VARCHAR(10)) + ';'
    EXEC (@SQL)
    PRINT  ' Process ' + CAST(@SPID AS VARCHAR(10)) +' has been killed'
    FETCH NEXT FROM Murderer INTO @SPID
    END 

CLOSE Murderer
DEALLOCATE Murderer

আমি আমার ব্লগে এটি সম্পর্কে এখানে লিখেছি: http://www.pigeonsql.com/single-post/2016/12/13/Kill-all-connifications-on-DB-by-Cursor


0
SELECT
    spid,
    sp.[status],
    loginame [Login],
    hostname, 
    blocked BlkBy,
    sd.name DBName, 
    cmd Command,
    cpu CPUTime,
    memusage Memory,
    physical_io DiskIO,
    lastwaittype LastWaitType,
    [program_name] ProgramName,
    last_batch LastBatch,
    login_time LoginTime,
    'kill ' + CAST(spid as varchar(10)) as 'Kill Command'
FROM master.dbo.sysprocesses sp 
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
WHERE sd.name NOT IN ('master', 'model', 'msdb') 
--AND sd.name = 'db_name' 
--AND hostname like 'hostname1%' 
--AND loginame like 'username1%'
ORDER BY spid

/* If a service connects continously. You can automatically execute kill process then run your script:
DECLARE @sqlcommand nvarchar (500)
SELECT @sqlcommand = 'kill ' + CAST(spid as varchar(10))
FROM master.dbo.sysprocesses sp 
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
WHERE sd.name NOT IN ('master', 'model', 'msdb') 
--AND sd.name = 'db_name' 
--AND hostname like 'hostname1%' 
--AND loginame like 'username1%'
--SELECT @sqlcommand
EXEC sp_executesql @sqlcommand
*/

-1

আমি নীচের সহজ কোড সহ সফলভাবে পরীক্ষা করেছি

USE [master]
GO
ALTER DATABASE [YourDatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

2
set SINGLE_USERইতিমধ্যে যখন একটি একক সক্রিয় সংযোগ ছিল তখন আমার সমস্যা ছিল।
ivan_pozdeev
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.