साथी एमवीपी जेमी थॉमसन ने हाल ही में बताया कि SQL सर्वर में एक "गलत परिणाम" बग है जो निम्न स्थितियों के सत्य होने पर स्वयं प्रकट हो सकता है:
- आपके पास एक अनुक्रमित दृश्य है जो कम से कम दो तालिकाओं को जोड़ता है;
- उन तालिकाओं को एकल-स्तंभ विदेशी कुंजी द्वारा किसी भी दिशा में बाधित किया गया है;
- आप
MERGE
. का उपयोग करके आधार तालिका (तालिकाओं) में अपडेट करते हैं जिसमेंUPDATE
both दोनों शामिल हैं और (हटाएं
यासम्मिलित करें
) क्रियाएं; और, - आप बाद में ऐसे प्रश्न जारी करते हैं जो दृश्य पर सूचकांक का संदर्भ देते हैं (जानबूझकर या नहीं)।
दुर्भाग्य से, समस्या का वर्णन करने वाला नॉलेज बेस आलेख (KB #2756471) विवरण पर बहुत हल्का है। वे आपको यह नहीं बताते कि समस्या को कैसे पुन:उत्पन्न किया जाए, या यहां तक कि क्या, विशेष रूप से, आपको यह देखना चाहिए कि क्या यह आपको प्रभावित करता है; और वे MERGE
. का जिक्र तक नहीं करते (जो वास्तव में समस्या का मूल है, न कि NOEXPAND
, और एक साधारण अद्यतन नहीं)। कनेक्ट आइटम में कुछ अतिरिक्त विवरण हैं जो फिक्स के बारे में लाए हैं; उम्मीद है कि KB आलेख को बहुत पहले अधिक विवरण के साथ अपडेट किया जाएगा।
इस बीच, आप जो परिणाम देख सकते हैं वह गलत डेटा है - या बेहतर शब्दों में कहें तो पुराना डेटा :क्वेरी आपको अपडेट की गई पंक्तियों का पुराना संस्करण दिखा सकती है! मैंने एडवेंचरवर्क्स में इस परिदृश्य को पुन:पेश करने की कोशिश में कुछ मिनट बिताए, और बुरी तरह विफल रहा। शुक्र है, पॉल व्हाइट (ब्लॉग | @SQL_Kiwi) ने परिदृश्य का वर्णन करते हुए और इस मुद्दे का पूर्ण रेप्रो दिखाते हुए एक उत्कृष्ट पोस्ट लिखा।
मुझे नहीं लगता कि मैं इस बात पर जोर दे सकता हूं कि यह कितना गंभीर है।
निश्चित रूप से लाखों ग्राहक अनुक्रमित दृश्यों का उपयोग कर रहे हैं, उनमें से कई ने MERGE
का उपयोग करने के लिए अपने DML कोड को माइग्रेट किया है , और उनमें से बड़ी संख्या में एंटरप्राइज़ संस्करण पर हैं (या नहीं हैं लेकिन NOEXPAND
का उपयोग कर रहे हैं संकेत या सीधे सूचकांक को संदर्भित कर रहे हैं)। पॉल ने तुरंत बताया कि NOEXPAND
एंटरप्राइज़ संस्करण में समस्या को पुन:उत्पन्न करने की आवश्यकता नहीं है, और बग को पुन:उत्पन्न करने के लिए आवश्यक कई अन्य विवरणों की भी खोज की है।
इस पोस्ट का उद्देश्य जेमी या पॉल की पोस्ट से कोई गड़गड़ाहट चोरी करना नहीं है; चिंता को दोहराने और इस मुद्दे के बारे में जागरूकता बढ़ाने का सिर्फ एक प्रयास। यदि आप संचयी अद्यतनों को अनदेखा करने, सर्विस पैक के लिए प्रतीक्षा करने का विकल्प चुनने की आदत में हैं, और इस बात की कोई संभावना है कि यह समस्या अभी आपको प्रभावित कर रही है, तो आप इसे स्वयं पर देय हैं, न कि अपने हितधारकों और ग्राहकों का उल्लेख करने के लिए। इस मुद्दे को गंभीरता से।
तो आपको क्या करना चाहिए?
खैर, आप आगे क्या करते हैं यह इस बात पर निर्भर करता है कि आप SQL सर्वर का कौन सा संस्करण और संस्करण चला रहे हैं, और क्या बग वास्तव में आपको प्रभावित करता है (या कर सकता है)।
- आपको अपनी शाखा के लिए नवीनतम संचयी अपडेट अपडेट करना चाहिए:
शाखा सीयू में तय निर्माण न्यूनतम निर्माण आवश्यक
अपडेट लागू करने के लिएKB आलेख
(डाउनलोड करें)2008 सर्विस पैक 3 CU #8 10.0.0.5828 10.00.5500 KB #2771833 2008 R2 सर्विस पैक 1 CU #10 10.50.2868 10.50.2500 KB #2783135 2008 R2 सर्विस पैक 2 CU #4 10.50.4270 10.0.0.4000 KB #2777358 2012 RTM CU #5 11.00.2395 11.00.2100 KB #2777772 2012 सर्विस पैक 1 CU #2 11.00.3339 11.00.3000 KB #2790947 तालिका 1 :वह बनाता है जिसमें सुधार होता है
- यदि आप सुधार लागू नहीं करते हैं, तो आपको यह सत्यापित करने के लिए अपने विचारों के सभी संदर्भों का परीक्षण करने की आवश्यकता है कि वे सभी मामलों में सही परिणाम लौटाते हैं - जिसमें आपके द्वारा
MERGEका उपयोग करके आधार तालिकाओं को अपडेट करने के बाद भी शामिल है। कोड> . यदि वे नहीं करते (या आपको संदेह है कि वे बाद में प्रभावित हो सकते हैं), तो आपको सभी प्रभावित दृश्यों पर संकुल अनुक्रमणिका का पुनर्निर्माण करना चाहिए (या
DBCC CHECKTABLE
का उपयोग करके अनुक्रमित दृश्य (दृश्यों) की मरम्मत करना चाहिए। , जैसा कि पॉल ने अपनी पोस्ट में वर्णित किया है), औरMERGE
. का उपयोग करना बंद कर दें इन तालिकाओं के विरुद्ध जब तक आपने सुधार लागू नहीं किया है। अगर आपMERGE
. का इस्तेमाल करना जारी रखते हैं आधार तालिकाओं के विरुद्ध, समस्या से बचने के लिए दृश्यों की मरम्मत जारी रखने के लिए तैयार रहें।
- एक त्वरित समाधान यह होगा कि क्षतिग्रस्त अनुक्रमित दृश्य को आवश्यक निम्न विधियों में से किसी एक का उपयोग करके उपयोग किए जाने से रोका जाए:
- क्वेरी संकेत लागू करें
विकल्प (विस्तार दृश्य)
सभी प्रासंगिक प्रश्नों के लिए; - दृश्य पर अनुक्रमणिका के किसी भी स्पष्ट संदर्भ को हटा दें;
- मानक या अन्य संस्करणों में जहां अनुक्रमित दृश्य स्वचालित रूप से मेल नहीं खाते हैं,
NOEXPAND
के सभी उदाहरणों को हटा दें .
लेकिन यह, निश्चित रूप से, अनुक्रमित दृष्टिकोण के उद्देश्य को काफी हद तक विफल कर देगा - साथ ही सूचकांक को गिरा भी सकता है। उस ने कहा, गलत परिणाम जल्दी प्राप्त करने की तुलना में, सही परिणाम धीरे-धीरे प्राप्त करना बेहतर है; तो शायद यह ठीक है।
- क्वेरी संकेत लागू करें
SQL Server 2008 SP3
SQL Server 2008 R2 SP1/SP2
SQL Server 2012 RTM/SP1
यदि आप इनमें से किसी एक बिल्ड पर हैं तो आपके विकल्प:
SQL Server 2008 RTM/SP1/SP2
SQL Server 2008 R2 RTM
दुर्भाग्य से, आप एक ऐसे निर्माण पर हैं जो अब मुख्यधारा के समर्थन में नहीं है, और यह संभावना नहीं है कि यह समस्या आपके लिए ठीक हो जाएगी (जब तक कि आप विस्तारित समर्थन पर न हों और आप बहुत अधिक शोर न करें)। इसलिए आपके विकल्प यहां सीमित हैं - या तो ऊपर दी गई तालिका के अनुसार किसी समर्थित शाखा में जाएं, और संचयी अपडेट लागू करें, या पहले बताए गए अन्य विकल्पों में से एक चुनें।
एसक्यूएल सर्वर 2000
एसक्यूएल सर्वर 2005
खैर, बुरी खबर यह है कि आप भी एक ऐसे निर्माण पर हैं जो अब समर्थित नहीं है। अच्छी खबर यह है कि इस विशिष्ट मामले में इससे कोई फर्क नहीं पड़ता - आप MERGE
का उपयोग नहीं कर सकते वैसे भी, इसलिए यह बग आपको प्रभावित नहीं कर सकता।
अन्य MERGE मुद्दे
अफसोस की बात है कि यह उस पहली बग से बहुत दूर है जिसे हमने MERGE
. के साथ देखा है , और यह संभवतः अंतिम नहीं होगा। यहां एक दर्जन . का त्वरित चयन दिया गया है मर्ज
बग जो अभी भी Connect पर सक्रिय के रूप में चिह्नित हैं:
- #773895 :MERGE गलत तरीके से अद्वितीय कुंजी उल्लंघनों की रिपोर्ट करता है
- #766165 :MERGE प्रति पंक्ति फ़िल्टर किए गए इंडेक्स का मूल्यांकन करता है, पोस्ट ऑपरेशन का नहीं, जो फ़िल्टर किए गए इंडेक्स उल्लंघन का कारण बनता है
- #723696 :मूल मर्ज अपसर्ट गतिरोध पैदा कर रहा है
- #713699 :सिस्टम पुष्टि जांच विफल हो गई है ("cxrowset.cpp":1528)
- #699055 :मर्ज क्वेरी प्लान FK और CHECK बाधा उल्लंघनों की अनुमति देते हैं
- #685800 :पैरामीटरयुक्त DELETE और MERGE अनुमति दें विदेशी कुंजी प्रतिबंध उल्लंघन
- #654746 :SQL2008 SP2 में मर्ज अभी भी "एक गैर-नल-सक्षम कॉलम के मान को NULL पर सेट करने का प्रयास" से ग्रस्त है
- #635778 :SQL MERGE स्टेटमेंट के मेल नहीं खाते और मैच किए गए हिस्से अनुकूलित नहीं हैं
- #633132 :फ़िल्टर किए गए स्रोत के साथ विलय ठीक से काम नहीं करता
- #596086 :INSERT/DELETE का उपयोग और फ़िल्टर किए गए इंडेक्स के दौरान MERGE स्टेटमेंट बग
- #583719 :MERGE स्टेटमेंट कुछ परिदृश्यों में गैर-शून्य परिकलित कॉलम को गलत तरीके से मानता है
- #539084 :MERGE Stmt :गैर-कुंजी कॉलम पर खोज की स्थिति और स्रोत व्युत्पन्न तालिका में ORDER BY पूरी तरह से MERGE को तोड़ देता है
अब, यह मामला हो सकता है कि इनमें से कुछ बग्स को वास्तव में ठीक कर दिया गया है, लेकिन उनकी स्थिति गलत है क्योंकि लूप बैक टू कनेक्ट को बंद नहीं किया गया है। अगर ऐसा है भी, तो यह उन सभी के लिए सही नहीं हो सकता (और संभावित रूप से अन्य लोगों के लिए जिन्हें मैंने उजागर नहीं किया)।
इसके अलावा, डैन गुज़मैन द्वारा यह प्रदर्शित किया गया है कि MERGE
दौड़ की स्थिति और अन्य समवर्ती मुद्दों से प्रतिरक्षा नहीं है। इसका समाधान HOLDLOCK
. का उपयोग करना है (या एक उच्च अलगाव स्तर); हालांकि, यह एक आम गलत धारणा है कि MERGE
पूरी तरह से परमाणु है और इस समस्या से बिल्कुल भी ग्रस्त नहीं है। इसलिए मुझे आश्चर्य होगा:कितने MERGE
वहां दिए गए बयानों में HOLDLOCK
. शामिल हैं (या SERIALIZABLE
. के तहत क्रियान्वित किया जा रहा है )? समवर्ती से संबंधित मुद्दों के लिए कितनों का पूरी तरह से परीक्षण किया गया है?
निष्कर्ष
व्यक्तिगत रूप से, मुझे लगता है कि वाक्यविन्यास बहुत अच्छा है (यद्यपि सीखना कठिन है), लेकिन हर बार जब कोई मुद्दा सामने आता है, तो यह मौजूदा डीएमएल को नए निर्माण के साथ बदलने की व्यावहारिकता में मेरा विश्वास कम कर देता है।
इसे ध्यान में रखते हुए, चिकन लिटिल नहीं होना चाहिए, लेकिन मैं किसी को भी MERGE
का उपयोग करने की अनुशंसा करने में सहज महसूस नहीं करूंगा। जब तक कि वे अत्यंत व्यापक परीक्षण लागू नहीं करते। इनमें से कुछ मुद्दे मानक UPSERT
. के साथ भी मौजूद हैं पद्धतियां, लेकिन वहां समस्याएं अधिक स्पष्ट हैं। मर्ज करें
, केवल अपनी एकल-कथन प्रकृति के माध्यम से, आपको जादू में विश्वास करना चाहता है। हो सकता है कि किसी दिन यह वितरित हो जाए, लेकिन अभी मुझे पता है कि यह बिना किसी गंभीर मदद के किसी व्यक्ति को आधे में नहीं देख पाएगा।