जस्टिन ग्रांट का जवाब बताता है कि LOCK_ESCALATION
सेटिंग सामान्य रूप से क्या करती है, लेकिन एक महत्वपूर्ण विवरण याद आती है और यह नहीं समझाती है कि एसएसएमएस उस कोड को क्यों बनाता है जो इसे सेट करता है। विशेष रूप से, यह बहुत ही अजीब लग रहा है कि LOCK_ESCALATION
यह स्क्रिप्ट में अंतिम कथन के रूप में सेट है।
मैंने कुछ परीक्षण किए और यहां जो कुछ हो रहा है, उसकी मेरी समझ है।
लघु संस्करण
ALTER TABLE
एक कॉलम में जुड़ने वाले कॉलम को जोड़ने, छोड़ने या बदलने का विवरण तालिका में एक स्कीमा संशोधित (SCH-M) लॉक लेता है, जिसका तालिका की LOCK_ESCALATION
सेटिंग से कोई लेना-देना नहीं है । LOCK_ESCALATION
DML बयान (दौरान व्यवहार ताला को प्रभावित करता है INSERT
, UPDATE
, DELETE
, आदि), DDL बयान के दौरान नहीं ( ALTER
)। SCH-M लॉक हमेशा इस उदाहरण में पूरे डेटाबेस ऑब्जेक्ट का टेबल होता है।
यह संभावना है कि भ्रम कहां से आता है।
SSMS ALTER TABLE <TableName> SET (LOCK_ESCALATION = ...)
अपने स्क्रिप्ट को सभी मामलों में जोड़ता है , तब भी जब इसकी आवश्यकता नहीं है। ऐसे मामलों में जब इस कथन की आवश्यकता होती है, इसे तालिका की वर्तमान सेटिंग को संरक्षित करने के लिए जोड़ा जाता है, न कि उस स्क्रिप्ट में होने वाले टेबल स्कीमा में परिवर्तन के दौरान तालिका को कुछ विशिष्ट तरीके से लॉक करने के लिए ।
दूसरे शब्दों में, तालिका को पहले ALTER TABLE ALTER COLUMN
स्टेटमेंट पर SCH-M लॉक के साथ लॉक किया गया है, जबकि टेबल स्कीमा को बदलने का सारा काम किया गया है। अंतिम ALTER TABLE SET LOCK_ESCALATION
कथन इसे प्रभावित नहीं करता है। यह केवल भविष्य DML बयान (को प्रभावित करता है INSERT
, UPDATE
, DELETE
, आदि) कि तालिका के लिए।
पहली नज़र में ऐसा लगता SET LOCK_ESCALATION = TABLE
है कि इस तथ्य से कोई लेना-देना नहीं है कि हम पूरी तालिका बदल रहे हैं (हम यहां अपना स्कीमा बदल रहे हैं), लेकिन यह भ्रामक है।
दीर्घ संस्करण
जब कुछ मामलों में तालिका में फेरबदल किया जाता है तो SSMS एक स्क्रिप्ट उत्पन्न करता है जो पूरी तालिका को पुन: बनाता है और कुछ सरल मामलों में (जैसे किसी स्तंभ को जोड़ना या छोड़ना) स्क्रिप्ट तालिका को फिर से नहीं बनाती है।
आइए इस नमूना तालिका को एक उदाहरण के रूप में लेते हैं:
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL,
[Col1] [nvarchar](50) NOT NULL,
[Col2] [int] NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
प्रत्येक तालिका में एक LOCK_ESCALATION
सेटिंग है, जो TABLE
डिफ़ॉल्ट रूप से सेट है । आइए इसे यहां बदलें:
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
अब, यदि मैं Col1
SSMS टेबल डिज़ाइनर में टाइप बदलने की कोशिश करता हूँ , SSMS एक स्क्रिप्ट बनाता है जो पूरी टेबल को फिर से बनाता है:
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_Test
(
ID int NOT NULL,
Col1 nvarchar(10) NOT NULL,
Col2 int NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_Test SET (LOCK_ESCALATION = DISABLE)
GO
IF EXISTS(SELECT * FROM dbo.Test)
EXEC('INSERT INTO dbo.Tmp_Test (ID, Col1, Col2)
SELECT ID, CONVERT(nvarchar(10), Col1), Col2 FROM dbo.Test WITH (HOLDLOCK TABLOCKX)')
GO
DROP TABLE dbo.Test
GO
EXECUTE sp_rename N'dbo.Tmp_Test', N'Test', 'OBJECT'
GO
ALTER TABLE dbo.Test ADD CONSTRAINT
PK_Test PRIMARY KEY CLUSTERED
(
ID
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
COMMIT
आप ऊपर देख सकते हैं कि यह LOCK_ESCALATION
नई बनाई गई तालिका के लिए सेट है । SSMS यह तालिका की वर्तमान सेटिंग को संरक्षित करने के लिए करता है। SSMS इस लाइन को उत्पन्न करता है, भले ही सेटिंग का वर्तमान मान डिफ़ॉल्ट TABLE
मान हो। यदि मैं भविष्य में इस डिफ़ॉल्ट परिवर्तन को सुरक्षित और स्पष्ट और संभव भविष्य की समस्याओं को रोक सकता हूं, तो मुझे लगता है। यह समझ में आता है।
इस उदाहरण में SET LOCK_ESCALATION
कथन को उत्पन्न करना वास्तव में आवश्यक है , क्योंकि तालिका को नए सिरे से बनाया गया है और इसकी सेटिंग को संरक्षित किया जाना है।
अगर मैं SSMS टेबल डिज़ाइनर का उपयोग करके तालिका में एक साधारण बदलाव करने की कोशिश करता हूं, जैसे कि एक नया कॉलम जोड़ना, तो SSMS एक स्क्रिप्ट बनाता है जो तालिका को फिर से नहीं बनाता है:
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Test ADD
NewCol nchar(10) NULL
GO
ALTER TABLE dbo.Test SET (LOCK_ESCALATION = DISABLE)
GO
COMMIT
जैसा कि आप देख सकते हैं, यह अभी भी ALTER TABLE SET LOCK_ESCALATION
बयान जोड़ता है , भले ही इस मामले में इसकी बिल्कुल भी आवश्यकता नहीं है। पहला ALTER TABLE ... ADD
वर्तमान सेटिंग नहीं बदलता है। मुझे लगता है, एसएसएमएस डेवलपर्स ने फैसला किया कि यह निर्धारित करने के प्रयास के लायक नहीं है कि यह ALTER TABLE SET LOCK_ESCALATION
कथन किस मामले में बेमानी है और इसे हमेशा उत्पन्न करना है, बस सुरक्षित रहने के लिए। हर बार इस बयान को जोड़ने में कोई बुराई नहीं है।
एक बार फिर, तालिका-चौड़ी LOCK_ESCALATION
सेटिंग अप्रासंगिक है जबकि तालिका स्कीमा ALTER TABLE
विवरण के माध्यम से बदल जाती है । LOCK_ESCALATION
सेटिंग केवल डीएमएल स्टेटमेंट्स के लॉकिंग व्यवहार को प्रभावित करती है, जैसे UPDATE
।
अंत में, एक उद्धरण ALTER TABLE
, मेरा जोर:
ALTER TABLE में निर्दिष्ट परिवर्तन तुरंत लागू हो जाते हैं। यदि परिवर्तनों को तालिका में पंक्तियों के संशोधनों की आवश्यकता होती है, तो ALTER TABLE पंक्तियों को अपडेट करती है। अन्य तालिका में एक स्कीमा संशोधित (SCH-M) लॉक को सुनिश्चित करने के लिए सुनिश्चित करें कि परिवर्तन के दौरान तालिका के लिए कोई अन्य कनेक्शन संदर्भ मेटाडेटा भी नहीं है।, सिवाय ऑनलाइन इंडेक्स ऑपरेशंस के जिन्हें अंत में बहुत ही कम SCH-M लॉक की आवश्यकता होती है। ALTER TABLE ... SWITCH ऑपरेशन में, लॉक को स्रोत और लक्ष्य तालिकाओं दोनों पर अधिग्रहित किया जाता है। तालिका में किए गए संशोधन लॉग और पूरी तरह से पुनर्प्राप्त करने योग्य हैं। परिवर्तन जो बहुत बड़ी तालिकाओं में सभी पंक्तियों को प्रभावित करते हैं, जैसे कि एक कॉलम को ड्रॉप करना या SQL सर्वर के कुछ संस्करणों पर, डिफ़ॉल्ट मान के साथ एक नॉट NULL कॉलम को जोड़ने में, कई लॉग रिकॉर्ड्स को पूरा करने और उत्पन्न करने में लंबा समय लग सकता है। किसी भी INSERT, UPDATE, या DELETE कथन के रूप में इन सावधानियों के बयान को उसी देखभाल के साथ निष्पादित किया जाना चाहिए जो इन पंक्तियों को प्रभावित करता है।