SQL सर्वर डेटाबेस को छोड़ नहीं सकता <dbname> क्योंकि यह वर्तमान में उपयोग में है ... लेकिन कोई सत्र प्रदर्शित नहीं हुआ


72

जब मैं एक डेटाबेस को छोड़ने की कोशिश करता हूं तो मुझे त्रुटि मिलती है "डेटाबेस को छोड़ नहीं सकता" dbname "क्योंकि यह वर्तमान में उपयोग में है"। हालाँकि, जब मैं दौड़ता हूं sp_who2, तो निश्चित रूप से इस डेटाबेस से जुड़ा कोई सत्र नहीं होता है। मैंने डेटाबेस को भी सेट कर दिया है single_user mode with rollback immediate

ये क्यों हो रहा है?

जवाबों:


20

सुनिश्चित करें कि आपके पास उस db पर डेटाबेस स्नैपशॉट जैसी निर्भरता नहीं है जिसे आप निकालना चाहते हैं। हालाँकि, त्रुटि संदेश अन्यथा दिखाई देगा। क्या आप सुनिश्चित हैं कि कोई छिपी हुई प्रक्रिया नहीं है जो आपके डेटाबेस से जुड़ रही है? एक अच्छा तरीका एक स्क्रिप्ट को चलाना होगा जो सभी सत्रों को मारता है और तुरंत डेटाबेस का नाम बदलकर दूसरे नाम पर रखता है और फिर डेटाबेस को छोड़ देता है।

इस चयन के आधार पर एक कर्सर बनाएँ:

  select  d.name , convert (smallint, req_spid) As spid
      from master.dbo.syslockinfo l, 
           master.dbo.spt_values v,
           master.dbo.spt_values x, 
           master.dbo.spt_values u, 
           master.dbo.sysdatabases d
      where   l.rsc_type = v.number 
      and v.type = 'LR' 
      and l.req_status = x.number 
      and x.type = 'LS' 
      and l.req_mode + 1 = u.number
      and u.type = 'L' 
      and l.rsc_dbid = d.dbid 
      and rsc_dbid = (select top 1 dbid from 
                      master..sysdatabases 
                      where name like 'my_db')

कर्सर के अंदर मुद्दा:

SET @kill_process =  'KILL ' + @spid      
            EXEC master.dbo.sp_executesql @kill_process
                   PRINT 'killed spid : '+ @spid

कर्सर को बंद करने और डील करने के बाद:

sp_dboption 'my_db', 'single user', 'TRUE'

go

sp_renamedb 'my_db', 'my_db_old'

go

DROP DATABASE MY_DB_OLD 

कोड के लिए धन्यवाद - जो काम कर सकता है। जो मुझे समझ नहीं आ रहा है, वह "छिपा हुआ" सत्र क्या है? मैंने सोचा होगा कि sp_who और अन्य मेटाडेटा (DMV) सभी सत्रों को दिखाएंगे, अन्य लोग क्या उपयोग कर रहे हैं?
tuseau

हाँ, आम तौर पर आपको sp_who के माध्यम से सभी सक्रिय / गैर सक्रिय देखने में सक्षम होना चाहिए या मास्टर डीबी से sysprocesses तालिका को क्वेरी करना चाहिए। छिपे हुए से मेरा मतलब एक ऐसी प्रक्रिया से है जो एक एप्लिकेशन सेवा से फिर से जुड़ती है। चीयर्स।
yrushka

1
यह कई कारणों से पुरातन है: (1) पुराने-शैली के जोड़ (2) पिछड़े संगतता दृश्य (3) एक कर्सर और गतिशील SQL, जो KILL कमांड का एक गुच्छा चलाने के लिए होता है, जब एक ही ALTER करेगा (4) डीप्रॉप्टेशन जैसी कार्यविधियाँ।
हारून बर्ट्रेंड

1
दुर्भाग्य से मुझे नहीं लगता कि यह सवाल का जवाब देता है - प्रश्नकर्ता पूछ रहा है कि ऐसा क्यों हो रहा है, न कि कैसे हल किया जाए। जवाब काम करता है, लेकिन मुझे अभी भी नहीं पता है कि एक डेटाबेस को हटाने से मुझे क्या रखना है। @AaronBertrand ने "यहां तक ​​कि ऑब्जेक्ट एक्सप्लोरर भी अपराधी हो सकता है" का उल्लेख किया, जो वास्तव में डेटाबेस में से एक का कारण बन रहा था, लेकिन मैं यह कैसे बता सकता था कि यह निश्चित रूप से ऑब्जेक्ट एक्सप्लोरर था?
LearnByReading

यह मुझे त्रुटि देता है "अपनी खुद की प्रक्रिया को मारने के लिए KILL का उपयोग नहीं कर सकता"
नून्डर

80

एक अन्य डेटाबेस से जुड़े सत्र में एक खुला लेनदेन हो सकता है जो आपके डेटाबेस को भी प्रभावित करता है - sp_who2 केवल एक डेटाबेस दिखाएगा। यह SSMS में खुलने वाले ऑब्जेक्ट एक्सप्लोरर या ऑब्जेक्ट एक्सप्लोरर के विवरण के समान सरल भी हो सकता है, जो फिर से sp_who2 में केवल एक डेटाबेस दिखाएगा।

जिम्मेदार है कि सत्र खोजने की कोशिश कर परेशान मत करो ; बस उन सभी को एक कथन के साथ मारें (और सुनिश्चित करें कि यह एसएसएमएस की आपकी प्रति नहीं है जो जुड़ा हुआ है, उदाहरण के लिए एक और क्वेरी विंडो, ऑब्जेक्ट एक्सप्लोरर, आदि:

USE master;
GO
ALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO

अब आप इसे छोड़ पाएंगे, और डीडीएल का उपयोग करते हुए, यूआई नहीं:

DROP DATABASE dbname;

1
आपके उत्तर के लिए धन्यवाद, यह काम किया। लेकिन मुझे इस समाधान के साथ रहने में कठिनाई हो रही है: ऐसा क्यों है कि मैं इस त्रुटि के कारण कुछ डेटाबेस को नहीं छोड़ सकता हूं? मेरे पास कुछ डेटाबेस हैं जिन्हें एक वर्ष के लिए नहीं छुआ गया है और कोई प्रक्रिया या ओस्टेंसिबल लेनदेन नहीं है जो उनसे जुड़े हैं। क्या आप मुझे संभावित सेवाओं, या लेनदेन या इन डेटाबेस से जुड़ी किसी भी चीज़ को खोजने में मदद करने के लिए कुछ संकेत दे सकते हैं?
LearnByReading

1
वास्तव में, सभी मुझे क्या करना था USE master, तो DROP DATABASE dbname। जाहिर है कि सभी की जरूरत है सिर्फ "उपयोग" कुछ और है, DB जारी करने के लिए।
vapcguy

2
@vapcguy यह केवल तभी सच है जब आपकी वर्तमान क्वेरी विंडो केवल कनेक्शन है। यह आमतौर पर ऐसा नहीं है (और यही कारण है कि मेरे उत्तर "कहते हैं और सुनिश्चित करें कि यह एसएसएमएस की आपकी प्रति नहीं है जो जुड़ा हुआ है")।
हारून बर्ट्रेंड

20

जब आप DROPआदेश जारी करते हैं तो आपका वर्तमान डेटाबेस क्या होता है ? इसे इस्तेमाल करे:

use master
go
drop database mydb
go

यह भी सुनिश्चित करें कि आप जिस भी डेटाबेस को छोड़ना चाहते हैं, आप saउससे जुड़े हैं और नहीं dbo


मैं निश्चित रूप से मास्टर से जुड़ा हुआ हूं। मुझे किसी डेटाबेस को छोड़ने के लिए sa के रूप में कनेक्ट नहीं होना चाहिए। यह मुझे एक बग की तरह दिखता है - यह एक सत्र प्रदर्शित नहीं कर रहा है, या यह सोचता है कि उपयोग में एक सत्र है लेकिन ऐसा नहीं है।
tuseau

3
मैं बस इस के साथ पकड़ा गया - sqlcmd प्रॉम्प्ट से डेटाबेस के लिए संदर्भ के साथ ड्रॉप स्क्रिप्ट को चलाने की कोशिश की! रवींद्र
JonnyRaa

18

जब आप यूआई का उपयोग करते हैं तो एसएसएमएस क्या करता है, यह देखने के बारे में कैसा है, लेकिन इसे कार्रवाई के लिए स्क्रिप्ट जारी करने के लिए कहें? यहाँ पर SSMS क्या करता है जब आप DB पर राइट क्लिक करते हैं और Delete को चुनते हैं, तो मौजूदा कनेक्शन को बंद करने के लिए बॉक्स को चेक करें:

EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'yourdbname'
GO

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

USE [master]
GO

DROP DATABASE [yourdbname]
GO

..., निश्चित रूप से, यह बिना किसी लेन
swasheck

4
आप डेटाबेस को छोड़ रहे हैं, मुझे लगता है कि यह काफी ठीक है।
georgiosd

1
यह मेरे लिए काम किया! :)
लियोनार्डो त्रिमार्ची

5

मैंने कई बार इस स्थिति का सामना किया है और नीचे मैं क्या करता हूं:

जब स्पष्ट तरीके काम नहीं करते हैं ..... (जैसे आपकी स्थिति में):

Sysdat डेटाबेस से डेटाबेस आईडी का पता लगाएं।

फिर निष्पादित करें - sp_lockजो उदाहरण के साथ स्पाइड और डीबीआईडी ​​पर सभी ताले दिखाएगा।

डीबीआईडी ​​के साथ स्पिड्स को मारें जिसे आप ऑफ़लाइन या ड्रॉप करने की कोशिश कर रहे हैं।

हालांकि, प्रक्रिया थोड़ी मैनुअल है, इसे नीचे के रूप में स्वचालित किया जा सकता है:

IF OBJECT_ID('tempdb.dbo.#temp', 'U') IS NOT NULL
  DROP TABLE #temp;
create table #temp (spid int
                , dbid int
                ,ObjId bigint
                , IndId bigint
                ,Type varchar(5)
                ,resource varchar(max)
                ,Mode varchar(5)
                ,status varchar(10));
declare @dbid int
select @dbid =DB_ID(db_name())

insert into #temp
exec sp_lock

select * from #temp
where dbid = @dbid

2

मेरे लिए पहली बार काम करने वाले स्टैकऑवरफ़्लो पर वास्तव में सरल उत्तर मिला:

https://stackoverflow.com/a/7469167/261405

यहाँ उस जवाब से एसक्यूएल है:

DECLARE @DatabaseName nvarchar(50)
SET @DatabaseName = N'YOUR_DABASE_NAME'

DECLARE @SQL varchar(max)

SELECT @SQL = COALESCE(@SQL,'') + 'Kill ' + Convert(varchar, SPId) + ';'
FROM MASTER..SysProcesses
WHERE DBId = DB_ID(@DatabaseName) AND SPId <> @@SPId

--Use this to see results
SELECT @SQL 
--Uncomment this to run it
--EXEC(@SQL)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.