SQL Server 2008 R2 सर्विस पैक 2 के लिए संचयी अद्यतन 11 में शामिल फ़िक्सेस में से एक "गलत गतिरोध" को संबोधित करता है जो एक विशिष्ट परिदृश्य में हो सकता है (इस आलेख में बाद में समझाया गया)। दुर्भाग्य से, फिक्स एक नया बग पेश करता है, जहां RCSI (पढ़ें प्रतिबद्ध स्नैपशॉट अलगाव) के तहत SELECT क्वेरीज़ टेबल-लेवल इंटेंट-शेयर्ड लॉक लेना शुरू कर देती हैं। परिणामस्वरूप, आप 2008 R2 SP2 CU11 (या बाद में) लागू करने के बाद RCSI प्रश्नों के लिए बढ़ी हुई अवरोधन (और संभावित रूप से गतिरोध) देख सकते हैं।
आरसीएसआई का उपयोग करते समय लेखकों (और इसके विपरीत) को अवरुद्ध नहीं करने वाले पाठकों के आदी किसी भी व्यक्ति के लिए यह एक अवांछित आश्चर्य के रूप में आएगा। लेखन के समय RCSI बग का कोई समाधान नहीं है। वास्तव में, यूजीन कारपोविच द्वारा समस्या की रिपोर्ट करने के लिए बनाए गए कनेक्ट आइटम को "विल नॉट फिक्स" के रूप में बंद कर दिया गया है, हालांकि मैं समझता हूं कि यह निर्णय वर्तमान में समीक्षाधीन है।
आमतौर पर, यह समस्या इतनी बड़ी चिंता का विषय नहीं हो सकती है, क्योंकि संचयी अद्यतन आम तौर पर पूर्ण सर्विस पैक के रूप में व्यापक रूप से लागू नहीं होते हैं। हालाँकि, Microsoft ने हाल ही में घोषणा की थी कि SQL Server 2008 R2 के लिए एक अंतिम सर्विस पैक 3 होगा। यह सर्विस पैक मौजूदा SP2 संचयी अद्यतनों (CU13 तक और सहित) का एक सरल रोल अप होगा, लेकिन इसमें कोई नया सुधार नहीं होगा। इन सबका नतीजा यह है कि, जब तक इस दौरान कुछ नहीं बदलता, SP3 को लागू करने वाले उपयोगकर्ता अचानक CU11 में पेश किए गए RCSI बग से प्रभावित होने लगेंगे।
संपादित करें:इस लेख के प्रकाशित होने से ठीक पहले, Microsoft ने पुष्टि की थी कि यह प्रतिगमन SP3 में तय किया जाएगा।
वही "गलत गतिरोध" बग (जिसका फिक्स नया बग पेश करता है) को SQL Server 2012 सर्विस पैक 1 के लिए संचयी अद्यतन 8 में भी KB2923460 में वर्णित के रूप में ठीक किया गया था। SQL सर्वर 2012 के लिए फिक्स अलग है, और नहीं . करता है नई RCSI समस्या का परिचय दें।
जहां तक मैं बता सकता हूं, SQL सर्वर 2014 कभी भी किसी भी मुद्दे से प्रभावित नहीं हुआ। अन्यथा इंगित करने के लिए निश्चित रूप से कोई दस्तावेज नहीं है, और मैंने 2014 RTM, CU1 और CU2 पर जो परीक्षण किए हैं, वे किसी भी बग को पुन:उत्पन्न नहीं करते हैं।
2008 R2 RCSI बग
RCSI के तहत चलने वाली एक सेलेक्ट क्वेरी में आमतौर पर केवल एक स्कीमा स्टेबिलिटी (Sch-S) लॉक होता है, जो एक स्कीमा मॉडिफिकेशन (Sch-M) लॉक को छोड़कर अन्य सभी लॉक के साथ संगत होता है। जब CU11 (या बाद में) को SQL Server 2008 R2 इंस्टेंस पर लागू किया जाता है, तो ये क्वेरीज़ टेबल-लेवल इंटेंट-शेयर्ड (टैब-आईएस) लॉक लेना शुरू कर देती हैं। व्यवहार में अंतर प्रदर्शित करने के लिए निम्नलिखित परीक्षण स्क्रिप्ट का उपयोग किया जा सकता है:
USE master; GO SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET NOCOUNT ON; GO CREATE DATABASE RCSI; GO ALTER DATABASE RCSI SET READ_COMMITTED_SNAPSHOT ON; GO ALTER DATABASE RCSI SET ALLOW_SNAPSHOT_ISOLATION OFF; GO USE RCSI; GO CREATE TABLE dbo.Test ( id integer IDENTITY NOT NULL, col1 integer NOT NULL, CONSTRAINT PK_Test PRIMARY KEY CLUSTERED (id) ); GO INSERT dbo.Test (col1) VALUES (1), (2), (3), (4); GO -- Show locks DBCC TRACEON (1200, 3604, -1) WITH NO_INFOMSGS; SELECT * FROM dbo.Test; DBCC TRACEOFF (1200, 3604, -1) WITH NO_INFOMSGS; GO ALTER DATABASE RCSI SET SINGLE_USER WITH ROLLBACK IMMEDIATE; USE master; DROP DATABASE RCSI;
जब बग के बिना SQL Server 2008 R2 की आवृत्ति के विरुद्ध चलाया जाता है, तो डीबग आउटपुट परीक्षण कथन के लिए अपेक्षित एक एकल Sch-S लॉक दिखाता है:
OBJECT पर Sch-S लॉक प्राप्त करने की प्रक्रिया:7:2105058535:0 परिणाम:OKऑब्जेक्ट पर लॉक जारी करने की प्रक्रिया:7:2105058535:0
जब SQL Server 2008 R2 बिल्ड 10.50.4302 (या उच्चतर) के विरुद्ध चलाया जाता है तो आउटपुट निम्न के समान होता है:
OBJECT पर IS लॉक प्राप्त करने की प्रक्रिया:7:2105058535:0 परिणाम:OKऑब्जेक्ट पर लॉक जारी करने की प्रक्रिया:7:2105058535:0
ध्यान दें कि Sch-S लॉक को Tab-IS लॉक से बदल दिया गया है।
प्रभाव और न्यूनीकरण
एक इंटेंट-शेयर्ड (IS) लॉक अभी भी एक बहुत ही संगत लॉक है, लेकिन यह Sch-S की तरह समवर्ती-अनुकूल नहीं है। लॉक संगतता मैट्रिक्स से पता चलता है कि एक IS लॉक के साथ विरोध होता है:
- Sch-M (स्कीमा संशोधन) - Sch-S के अनुसार
- बीयू (थोक अपडेट)
- X (अनन्य)
एक्सक्लूसिव (X) लॉक के साथ असंगति का मतलब है कि RCSI के तहत एक रीड ब्लॉक हो जाएगा यदि एक समवर्ती प्रक्रिया उसी संसाधन पर एक विशेष लॉक रखती है। इसी तरह, एक लेखक जिसे एक विशेष लॉक की आवश्यकता होती है, यदि एक समवर्ती आरसीएसआई रीडर एक आईएस लॉक रखता है तो वह अवरुद्ध हो जाएगा। जब भी डेटा संशोधित किया जाता है, और लेन-देन के अंत तक आयोजित किया जाता है, तो विशेष ताले प्राप्त होते हैं, इसलिए बग का प्रभाव यह है कि आरसीएसआई के तहत पाठकों को समवर्ती लेखकों (और इसके विपरीत) द्वारा अवरुद्ध कर दिया जाएगा जब वे सीयू 11 लागू होने से पहले नहीं थे।
एक महत्वपूर्ण शमन कारक यह है कि बग केवल तालिका-स्तर . का कारण बनता है आशय-साझा ताला लिया जाना है। एक समवर्ती लेखक जिसे तालिका-स्तर . की आवश्यकता होती है अनन्य लॉक अवरुद्ध (और संभावित रूप से एक डेडलॉक) का कारण बन जाएगा। हालांकि, समवर्ती लेखक जिन्हें केवल निचले (जैसे पंक्ति, पृष्ठ या विभाजन) स्तर पर अनन्य लॉक की आवश्यकता होती है, वे नहीं होंगे अवरोध या गतिरोध का कारण। तालिका स्तर पर, ये लेखक केवल एक इंटेंट-एक्सक्लूसिव (IX) लॉक प्राप्त करेंगे, जो Tab-IS के साथ संगत है। ग्रैन्युलैरिटी के निचले स्तरों पर लिए गए अनन्य लॉक से कोई विरोध नहीं होगा।
अधिकांश प्रणालियों में, टेबल-लेवल एक्सक्लूसिव (टैब-एक्स) लॉक अपेक्षाकृत असामान्य होंगे। जब तक स्पष्ट रूप से TABLOCKX संकेत का उपयोग करने का अनुरोध नहीं किया जाता है, Tab-X लॉक के कुछ संभावित कारण हैं:
- निम्न ग्रैन्युलैरिटी से लॉक एस्केलेशन
- की-रेंज लॉक के लिए सपोर्टिंग इंडेक्स के बिना SERIALIZABLE का उपयोग करना
एक तकनीकी समाधान (अनावश्यक) तालिका संकेत जोड़ना है WITH (READCOMMITTED)
आरसीएसआई के तहत चलने वाली प्रत्येक क्वेरी में प्रत्येक तालिका में। यह बग को बायपास करने के लिए होता है इसलिए केवल एक Sch-S लॉक लिया जाता है, लेकिन यह शायद ही एक व्यावहारिक प्रस्ताव है।
इन कमियों के बावजूद, RCSI के तहत केवल पढ़ने के लिए क्वेरी के लिए Tab-IS लेना अभी भी गलत व्यवहार है। मुझे उम्मीद है कि सर्विस पैक 3 जारी होने से पहले इसे SQL Server 2008 R2 के लिए ठीक किया जा सकता है।
"गलत गतिरोध" बग
जैसा कि पहले उल्लेख किया गया है, RCSI बग को "गलत गतिरोध" बग के समाधान के दुष्प्रभाव के रूप में पेश किया गया है। यह पुराना मुद्दा KB2929464 में SQL Server 2008 R2 के लिए और KB2923460 में SQL Server 2012 के लिए प्रलेखित है। कोई भी दस्तावेज़ स्पष्टता (या सटीकता) का मॉडल नहीं है, लेकिन अंतर्निहित मुद्दा काफी दिलचस्प है, इसलिए मैं इसे यहां देखने में थोड़ा समय बिताना चाहता हूं।
अनिवार्य रूप से, गतिरोध तब होता है जब:
- एक ही तालिका से पढ़े गए तीन या अधिक समवर्ती लेनदेन
- UPDLOCK और TABLOCK संकेत तीनों मामलों में उपयोग किए जाते हैं
- डेटाबेस सेटिंग READ_COMMITTED_SNAPSHOT चालू है
ध्यान दें कि इससे कोई फर्क नहीं पड़ता कि लेन-देन किस अलगाव स्तर के अंतर्गत चलता है। बग को पुन:उत्पन्न करने के लिए, पहले नीचे सेटअप स्क्रिप्ट चलाएँ:
USE master; GO SET TRANSACTION ISOLATION LEVEL READ COMMITTED; GO CREATE DATABASE IncorrectDeadlock; GO ALTER DATABASE IncorrectDeadlock SET READ_COMMITTED_SNAPSHOT ON; GO USE IncorrectDeadlock; GO CREATE TABLE dbo.Test ( id integer IDENTITY NOT NULL, col1 integer NOT NULL, CONSTRAINT PK_Test PRIMARY KEY CLUSTERED (id) ); GO INSERT dbo.Test (col1) VALUES (1);
इसके बाद, निम्न स्क्रिप्ट को तीन अलग-अलग कनेक्शनों में चलाएँ (ध्यान दें कि लेन-देन खुला रहता है):
USE IncorrectDeadlock; GO SET TRANSACTION ISOLATION LEVEL READ COMMITTED; GO BEGIN TRANSACTION; SELECT T.id, T.col1 FROM dbo.Test AS T WITH (UPDLOCK, TABLOCK);
इस बिंदु पर, पहला सत्र एक परिणाम सेट लौटाएगा और अन्य दो अवरुद्ध हो जाएंगे। "गलत गतिरोध" तब उत्पन्न होता है जब पहला सत्र अपना लेन-देन पूरा करता है (या तो प्रतिबद्ध या वापस रोलिंग)। जब ऐसा होता है, तो अन्य दो सत्रों में से कोई एक गतिरोध की रिपोर्ट करेगा:
गतिरोध इसलिए होता है क्योंकि पहले से अवरुद्ध दो सत्रों में Tab-IX (टेबल-लेवल इंटेंट-एक्सक्लूसिव) होता है और दोनों अपने लॉक को Tab-X (टेबल-लेवल एक्सक्लूसिव) में बदलना चाहते हैं। Tab-IX दूसरे Tab-IX के साथ संगत है, लेकिन Tab-X नहीं। यह एक रूपांतरण गतिरोध है (और यहाँ विडंबना यह है कि UPDLOCK का उपयोग अक्सर रूपांतरण गतिरोध से बचने के लिए किया जाता है)।
अपनी इच्छानुसार तीन प्रश्नों के लिए लेन-देन अलगाव स्तर को बदलने के लिए स्वतंत्र महसूस करें। गतिरोध की परवाह किए बिना होगा, जब तक कि RCSI सक्षम है, उसी ताले के साथ। जब परीक्षण पूर्ण हो जाएं, तो परीक्षण डेटाबेस को हटा दें:
USE IncorrectDeadlock; ALTER DATABASE IncorrectDeadlock SET SINGLE_USER WITH ROLLBACK IMMEDIATE; USE master; DROP DATABASE IncorrectDeadlock;
विश्लेषण और स्पष्टीकरण
मुझे व्यक्तिगत रूप से याद नहीं है कि मैंने अपने कोड में UPDLOCK और TABLOCK का एक साथ उपयोग किया है। मेरे लिए, संकेतों का यह संयोजन सहज रूप से अजीब लगता है क्योंकि SQL सर्वर में टेबल-स्तरीय अपडेट लॉक नहीं है . तो, इसका भी क्या मतलब है मतलब UPDLOCK और TABLOCK संकेतों को एक साथ निर्दिष्ट करने के लिए?
दस्तावेज़ीकरण में यह कहना है:
अपडलॉकनिर्दिष्ट करता है कि लेन-देन पूरा होने तक अपडेट लॉक को लिया और रखा जाना है। UPDLOCK केवल रो-लेवल या पेज-लेवल पर रीड ऑपरेशंस के लिए अपडेट लॉक लेता है। अगर UPDLOCK को TABLOCK के साथ जोड़ दिया जाता है, या किसी अन्य कारण से टेबल-लेवल लॉक लिया जाता है, तो इसके बजाय एक एक्सक्लूसिव (X) लॉक लिया जाएगा।
इससे पता चलता है कि संकेत संयोजन का परिणाम एकल अनन्य टेबल लॉक होना चाहिए। वास्तव में, यह पूरी कहानी नहीं है:
SQL सर्वर 2000 में, UPDLOCK और TABLOCK संकेतों के संयोजन के परिणामस्वरूप Tab-S (एक साझा टेबल लॉक) लिया जाता है, जिसके बाद सभी अलगाव स्तरों के तहत Tab-X (अनन्य टेबल लॉक) में रूपांतरण किया जाता है, सिवाय UNCOMMITTED को छोड़कर। तालों के इस क्रम के परिणामस्वरूप एक गतिरोध हो सकता है जहाँ तीन या अधिक सत्र शामिल होते हैं:दो सत्र Tab-S प्राप्त करते हैं और दोनों Tab-X में परिवर्तित होने के लिए दूसरे पर प्रतीक्षा करते हैं। READ UNCOMMITTED के तहत, SQL Server 2000 Sch-S फिर Tab-X लेता है, जो गतिरोध (सिर्फ सामान्य अवरोधन) के लिए प्रवण नहीं है।
SQL सर्वर 2005 में आगे (बग फिक्स के बिना) लिए गए ताले केवल पर निर्भर करते हैं आरसीएसआई सक्षम है या नहीं, इस पर। यदि RCSI सक्षम है, तो सभी अलगाव स्तर Tab-IX लें और फिर Tab-X में कनवर्ट करें। यह क्रम बग फिक्स पते में गतिरोध पैदा करता है।
यदि RCSI सक्षम नहीं है, तो मिलान आइसोलेशन स्तर वैसा ही व्यवहार करते हैं जैसा उन्होंने SQL Server 2000 के तहत किया था (Tab-S को लेकर Tab-X में कनवर्ट करना)। (2005 के लिए नया) स्नैपशॉट अलगाव स्तर Sch-S और उसके बाद Tab-X लेता है। परिणामस्वरूप, RCSI सक्षम नहीं होने पर UPDLOCK, TABLOCK परिदृश्य में SI और READ UNCOMMITTED एकमात्र अलगाव स्तर हैं जो इस गतिरोध के लिए प्रवण नहीं हैं।
डेडलॉक फिक्स
जब UPDLOCK और TABLOCK को एक साथ निर्दिष्ट किया जाता है, तो सभी आइसोलेशन स्तरों के लिए फिक्स लॉक को बदल देता है , और चाहे आरसीएसआई सक्षम है या नहीं। फिक्स लागू होने के बाद, UPDLOCK और TABLOCK इंजन को Tab-SIX (टेबल-लेवल शेयर्ड विद इंटेंट एक्सक्लूसिव) हासिल करने का कारण बनते हैं, जिसे बाद में Tab-X में बदल दिया जाता है।
यह गतिरोध परिदृश्य से बचा जाता है क्योंकि Tab-SIX दूसरे Tab-SIX के साथ असंगत है। याद रखें, गतिरोध तब हुआ जब दो प्रक्रियाओं ने Tab-IX को Tab-X में बदलने की प्रतीक्षा की। Tab-IX के स्थान पर Tab-SIX के साथ, दोनों के लिए Tab-SIX को एक साथ रखना संभव नहीं है। परिणाम एक गतिरोध के बजाय एक सामान्य अवरोधन परिदृश्य है।
अंतिम विचार
"गलत गतिरोध" फिक्स एक विशेष गतिरोध परिदृश्य को हल करता है, लेकिन यह अभी भी उस व्यवहार में परिणाम नहीं देता है जिसकी मैं कल्पना करता हूं कि UPDLOCK और TABLOCK को निर्दिष्ट करने वाले लोग परिकल्पित हैं। यदि SQL सर्वर में Tab-U (टेबल-लेवल अपडेट) लॉक है, तो यह टेबल में समवर्ती परिवर्तनों को रोकेगा लेकिन समवर्ती पाठकों को अनुमति देगा। मैं कल्पना करता हूं कि इन संकेतों का एक साथ उपयोग करने वाले लोगों का इरादा क्या होगा, और मैं देख सकता हूं कि यह कैसे उपयोगी हो सकता है।
वर्तमान कार्यान्वयन (जहां टैब-एक्स को लापता टैब-यू के बजाय अंततः लिया जाता है) इस अपेक्षा से मेल नहीं खाता क्योंकि टैब-एक्स समवर्ती पढ़ने को रोकता है (जब तक कि एक पंक्ति-संस्करण अलगाव स्तर का उपयोग नहीं किया जाता है)। हम कई मामलों में TABLOCKX को भी निर्दिष्ट कर सकते हैं। तथ्य यह है कि फिक्स एक नया बग भी पेश करता है (केवल SQL Server 2008 R2 के उपयोगकर्ताओं के लिए) भी दुर्भाग्यपूर्ण है, खासकर यदि बग 2008 R2 SP3 में शामिल किया जाता है।
ध्यान दें कि 2008 R2 से पहले SQL सर्वर संस्करणों के लिए डेडलॉक फिक्स उपलब्ध नहीं कराया जा रहा है। इन संस्करणों में ऊपर वर्णित अनुसार UPDLOCK और TABLOCK के लिए जटिल लॉकिंग व्यवहार जारी रहेगा।
यूजीन कार्पोविच को मेरा धन्यवाद जिन्होंने आरसीएसआई के तहत डेटा संशोधन पर मेरे लेख पर एक टिप्पणी में इस मुद्दे को सबसे पहले मेरे ध्यान में लाया।