विदेशी कुंजियों को छोड़ने में लंबा समय क्यों लगता है?


13

मैंने एक स्क्रिप्ट बनाई है, जो एक समय में, डेटाबेस से सभी विदेशी कुंजियों को इस तरह से हटा देती है:

ALTER TABLE MyTable1 DROP CONSTRAINT FK_MyTable1_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col2

मुझे आश्चर्य होता है कि स्क्रिप्ट में लंबा समय लगता है: प्रत्येक DROP FK के लिए औसतन 20 सेकंड। अब, मैं समझता हूं कि एफके बनाना एक बड़ी बात हो सकती है, क्योंकि सर्वर को यह जांचना होगा कि एफके बाधा शुरुआत से उल्लंघन नहीं है, लेकिन गिर रहा है? FKs को इतनी देर तक छोड़ने पर एक सर्वर क्या करता है? यह मेरी अपनी जिज्ञासा के लिए है, और यह समझने के लिए कि क्या चीजें तेजी से बनाने का कोई तरीका है। एफके को हटाने में सक्षम होना (न केवल उन्हें अक्षम करना) मुझे एक प्रवास के दौरान बहुत तेज होने की अनुमति देगा, और इसलिए डाउनटाइम को कम से कम करें।


1
हो सकता है कि एक और प्रक्रिया स्थानों ने आपके डेटाबेस पर स्कीमा ताले साझा किए, ड्रॉप FK प्रक्रिया को मजबूर करने के लिए उन प्रक्रियाओं को समाप्त करने के लिए मजबूर किया? ड्रॉप FK चलाने की कोशिश करें और फिर अवरुद्ध करने के लिए तुरंत sp_who2 की जाँच करें।
डैनियल हटमाचर

मैं उल्लेख करना भूल गया, इस डेटाबेस पर कोई अन्य प्रक्रिया नहीं चल रही है। लेकिन एक ही सर्वर पर अन्य डेटाबेस पर हैं।
carlo.borreo

जवाबों:


12

एक बाधा को छोड़ने के लिए एक Sch-M (स्कीमा संशोधन) लॉक की आवश्यकता होती है जो संशोधन के दौरान तालिका को क्वेरी करने के लिए दूसरों को अवरुद्ध कर देगा। आप शायद उस ताले को पाने के लिए इंतजार कर रहे हैं और तब तक इंतजार करना होगा जब तक कि उस तालिका के खिलाफ चल रहे सभी प्रश्न समाप्त नहीं हो जाते।
एक रनिंग क्वेरी में टेबल पर एक Sch-S (स्कीमा स्थिरता) लॉक होता है और वह लॉक Sch-M लॉक के साथ असंगत होता है।

से लॉक मोड, स्कीमा ताले

डेटाबेस इंजन एक टेबल डेटा डेफिनेशन लैंग्वेज (DDL) ऑपरेशन के दौरान स्कीमा मॉडिफिकेशन (Sch-M) लॉक का उपयोग करता है, जैसे कॉलम जोड़ना या टेबल को गिराना। उस समय के दौरान यह आयोजित किया जाता है, Sch-M लॉक तालिका में समवर्ती पहुंच को रोकता है। इसका मतलब है कि जब तक लॉक जारी नहीं किया जाता है तब तक Sch-M लॉक बाहर के सभी ऑपरेशनों को रोक देता है।

कुछ डेटा हेरफेर भाषा (डीएमएल) संचालन, जैसे टेबल ट्रंकेशन, समवर्ती संचालन द्वारा प्रभावित तालिकाओं तक पहुंच को रोकने के लिए Sch-M तालों का उपयोग करते हैं।

डेटाबेस इंजन क्वेरी का संकलन और निष्पादित करते समय स्कीमा स्थिरता (SCH-S) लॉक का उपयोग करता है। Sch-S ताले अनन्य (X) ताले सहित किसी भी लेन-देन के ताले को ब्लॉक नहीं करते हैं। इसलिए, एक टेबल पर एक्स ताले वाले अन्य लेनदेन, एक क्वेरी संकलित किए जाने के दौरान जारी रहता है। हालांकि, समवर्ती डीडीएल संचालन, और समवर्ती डीएमएल संचालन जो Sch-M तालों का अधिग्रहण करते हैं, उन्हें मेज पर नहीं किया जा सकता है।


कभी-कभी SSMS में तालिका को हाइलाइट करने से भी एक Sch-Sलॉक बन जाएगा, और मुझे संदेह है कि यह ओपी के मुद्दों का मूल कारण है।
जॉन आइज़ब्रेनर

5

मैं आपको एक उदाहरण के माध्यम से चलता हूं, तो आप देख सकते हैं कि इसमें लंबा समय क्यों लग रहा था। इस परीक्षण के लिए एक खाली डेटाबेस बनाना।

CREATE DATABASE [TestFK]
GO

2 टेबल बनाना।

 USE [TestFK]
 GO
CREATE TABLE dbo.[Address] (
      ADDRESSID   INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
       Address1    VARCHAR(50),
      City        VARCHAR(50),
      [State]     VARCHAR(10),
      ZIP     VARCHAR(10));
GO

CREATE TABLE dbo.Person (
       PersonID    INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
       LastName    VARCHAR(50) NOT NULL,
     FirstName   VARCHAR(50),
      AddressID   INT);
GO

व्यक्ति तालिका पर एक विदेशी कुंजी बाधा बनाना।

 USE [TestFK]
 GO
ALTER TABLE dbo.Person ADD CONSTRAINT FK_Person_AddressID FOREIGN KEY (AddressID)
REFERENCES dbo.Address(AddressID)
GO

दोनों तालिकाओं में कुछ डेटा डालें।

USE [TestFK]
GO
INSERT dbo.Address (Address1,City,[State],Zip)
  SELECT '123 Easy St','Austin','TX','78701'
    UNION
 SELECT '456 Lakeview','Sunrise Beach','TX','78643'
GO
INSERT dbo.Person (LastName,FirstName,AddressID)
    SELECT 'Smith','John',1
   UNION
 SELECT 'Smith','Mary',1
   UNION
 SELECT 'Jones','Max',2
GO

एक नई क्वेरी विंडो खोलें और इसे चलाएं (क्वेरी पूरा होने के बाद विंडो को बंद न करें)।

   USE [TestFK]
   GO
   BEGIN TRAN
   INSERT dbo.Person (LastName,FirstName,AddressID)
    SELECT 'Smith1','John1',1
    UNION
    SELECT 'Smith1','Mary1',1
    UNION
    SELECT 'Jones1','Max1',2

एक और क्वेरी विंडो खोलें और इसे चलाएं।

USE [TestFK]
GO
ALTER TABLE dbo.person DROP CONSTRAINT FK_Person_AddressID

आप देखेंगे कि आप अवरोध छोड़ रहे हैं (प्रतीक्षा कर रहे हैं) और अब क्वेरी को यह देखने के लिए चलाएं कि यह अधिक समय तक क्यों चल रहा है और यह किस ताले का इंतजार कर रहा है।

SELECT * FROM sys.dm_os_waiting_tasks 
WHERE blocking_session_id IS NOT NULL; 

एक बार जब आप अपना इंसर्ट ऑपरेशन कर लेते हैं, तो ड्रॉप बाधा तुरंत पूरी हो जाएगी क्योंकि अब ड्रॉप स्टेटमेंट आवश्यक लॉक हासिल कर सकता है।

आपके मामले के लिए आपको यह सुनिश्चित करने की आवश्यकता है कि कोई सत्र संगत लॉक नहीं कर रहा है, जो आवश्यक अवरोध / ताले प्राप्त करने के लिए ड्रॉप बाधा को रोक देगा।


डेटाबेस का उपयोग कोई और नहीं कर रहा था, लेकिन दूसरी ओर, मैं यह नहीं छोड़ सकता कि मेरे पास इस डेटाबेस पर एक खुली खिड़की थी। मैं एक और प्रयोग करूंगा।
carlo.borreo

1
जब आपका ड्रॉप स्टेटमेंट समाप्त हो रहा है तो इस क्वेरी को दूसरी विंडो से चलाएं। इससे आपको वही मिलेगा जो आप इंतजार कर रहे हैं। यहाँ से क्वेरी प्राप्त करें । मेरे पास मेरे उदाहरण में जितना विवरण दिया गया है, उससे कहीं अधिक इसका विवरण है।
SqlWorldWide
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.