it-swarm.asia

لا يمكن لـ SQL Server إسقاط قاعدة البيانات <dbname> لأنها قيد الاستخدام حاليًا ... ولكن لا توجد جلسات معروضة

عندما أحاول إسقاط قاعدة بيانات أحصل على الخطأ "لا يمكن إسقاط قاعدة البيانات" dbname "لأنها قيد الاستخدام حاليًا". ومع ذلك ، عندما أركض sp_who2 ، بالتأكيد لا توجد جلسات متصلة بقاعدة البيانات هذه. لقد قمت أيضًا بتعيين قاعدة البيانات إلى single_user mode with rollback immediate.

لماذا يحدث هذا؟

81
tuseau

تأكد من عدم وجود تبعيات مثل لقطات قاعدة البيانات على قاعدة البيانات التي تريد إزالتها. على الرغم من ذلك ، ستبدو رسالة الخطأ خلاف ذلك. هل أنت متأكد من عدم وجود عملية مخفية تتصل بقاعدة البيانات الخاصة بك؟ قد يكون النهج الجيد هو تشغيل برنامج نصي يقتل جميع الجلسات مباشرة وبعد إعادة تسمية قاعدة البيانات إلى اسم آخر ثم إسقاط قاعدة البيانات.

قم بإنشاء مؤشر على أساس هذا التحديد:

  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 
22
yrushka

قد يكون للجلسة المتصلة بقاعدة بيانات أخرى معاملة مفتوحة تؤثر أيضًا على قاعدة البيانات الخاصة بك - ستعرض sp_who2 قاعدة بيانات واحدة فقط. يمكن أيضًا أن يكون شيئًا بسيطًا مثل Object Explorer أو Object Explorer Details مفتوح في SSMS ، والذي سيعرض مرة أخرى قاعدة بيانات واحدة فقط في sp_who2.

لا تهتم بمحاولة find الجلسة المسؤولة ؛ فقط اقتلهم جميعًا ببيان واحد (وتأكد من أن نسختك من SSMS غير متصلة ، على سبيل المثال نافذة استعلام أخرى ، مستكشف الكائنات ، إلخ):

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

ستتمكن الآن من إسقاطها ، والقيام بذلك باستخدام DDL ، وليس واجهة المستخدم:

DROP DATABASE dbname;
92
Aaron Bertrand

ما هي قاعدة البيانات الحالية عند إصدار الأمر DROP؟ جرب هذا:

use master
go
drop database mydb
go

تأكد أيضًا من أنك متصل كـ sa وليس dbo في أي قاعدة بيانات تريد إسقاطها.

20
Gaius

ماذا عن مجرد رؤية ما يفعله SSMS عند استخدام واجهة المستخدم ولكن تطلب منه إصدار نص برمجي للإجراء؟ إليك ما يفعله SSMS عند النقر بزر الماوس الأيمن على قاعدة البيانات واختيار حذف ، ثم تحديد المربع لإغلاق الاتصالات الحالية:

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
18
Thiago Silva

لقد واجهت هذا الموقف مرات عديدة وأدناه هو ما أفعله:

عندما لا تعمل الطرق الواضحة ..... (كما هو الحال في وضعك):

تعرف على معرف قاعدة البيانات من قواعد البيانات.

ثم تنفيذ - sp_lock التي ستظهر كل الأقفال الموجودة في النسخة مع سبيد و dbid.

اقتل العنكبوتات مع dbid التي تحاول عدم الاتصال بالإنترنت أو إسقاطها.

على الرغم من أن العملية يدوية بعض الشيء ، يمكن أتمتة على النحو التالي:

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
5
Kin Shah

وجدت إجابة بسيطة حقًا على StackOverflow التي عملت لأول مرة بالنسبة لي:

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

إليك SQL من تلك الإجابة:

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)
3
Adrian Carr