2012-09-24 21 views
8

मैं एक रिपोर्टिंग मॉड्यूल के हिस्से के रूप में कई लंबे समय से चल रहे SQL क्वेरी निष्पादित कर रहा हूं। इन प्रश्नों को रन-टाइम पर गतिशील रूप से बनाया गया है। उपयोगकर्ता के इनपुट के आधार पर, वे एकल या बहु-कथन हो सकते हैं, एक या अधिक पैरामीटर हो सकते हैं और एक या अधिक डेटाबेस तालिकाओं पर काम कर सकते हैं - दूसरे शब्दों में, उनके रूप को आसानी से अनुमानित नहीं किया जा सकता है।लंबा पढ़ने के लिए SqlTransaction और IsolationLevel का उपयोग करें?

वर्तमान में, मैं तो बस इन बयानों एक साधारण SqlConnection पर

using (SqlConnection cn = new SqlConnection(ConnectionString)) { 
    cn.Open(); 
    // command 1 
    // command 2 
    // ... 
    // command N 
} 

को क्रियान्वित कर रहा हूँ, यानी क्योंकि इन प्रश्नों (वास्तव में बैचों क्वेरी) निष्पादित करने के लिए कुछ समय लग सकता है, मैं चिंतित ताले के बारे में टेबल पर पकड़े पढ़ता हूँ/अन्य उपयोगकर्ताओं के लिए लिखता है। बैच के निष्पादन के दौरान इन रिपोर्टों के डेटा में परिवर्तन होने पर यह कोई समस्या नहीं है; रिपोर्ट प्रश्नों को उन तालिकाओं पर अन्य परिचालनों पर कभी प्राथमिकता नहीं लेनी चाहिए, न ही उन्हें उन्हें बंद करना चाहिए।

सबसे लंबे समय से चल रहा है/बहु बयान कार्य है कि डेटा को संशोधित करने को शामिल के लिए, मैं लेनदेन का प्रयोग करेंगे। यहां अंतर यह है कि ये रिपोर्ट प्रश्न किसी भी डेटा को संशोधित नहीं कर रहे हैं। क्या मैं अपने अलगाव स्तर को नियंत्रित करने के लिए SqlTransaction में इन रिपोर्ट क्वेरी को लपेटने में सही होगा?

यानी:

using (SqlConnection cn = new SqlConnection(ConnectionString)) { 
    cn.Open(); 

    using (SqlTransaction tr = cn.BeginTransaction(IsolationLevel.ReadUncommitted)) { 
     // command 1 
     // command 2 
     // ... 
     // command N 

     tr.Commit(); 
    } 
} 

यह मेरा वांछित परिणाम प्राप्त होगा? क्या कोई लेनदेन करने में सही है, भले ही कोई डेटा संशोधित नहीं किया गया हो? क्या कोई और दृष्टिकोण है? लेन-देन में खिलवाड़ के बिना

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; 

जो एक ही मंशा को प्राप्त होता है,:

+0

रिपोर्ट रहना होगा [सही] (क्या मदद करता है http://blogs.msdn.com/b/sqlcat/archive/2007/02/01/previously-committed-rows-might- be-miss-if-nolock-hint-is-used.aspx) या नहीं? –

+0

@RemusRusanu रिपोर्ट लंबे समय तक डेटा का तात्कालिक स्नैपशॉट प्रदान करती है; उन्हें खाता परिवर्तनों को ध्यान में रखने की आवश्यकता नहीं है जो मध्य लेनदेन हो सकते हैं। कम उत्तराधिकार में उपयोगकर्ता द्वारा अंतर्निहित प्रश्नों को कई बार चलाने की संभावना है, और उपयोगकर्ता प्रत्येक बार परिणाम समान होने की अपेक्षा नहीं करेगा। –

+1

यह वास्तव में ऐसी रिपोर्ट है जो गंदे पढ़ने से प्रभावित (बुरी तरह) हो जाती है। गणना और समेकन यादृच्छिक रूप से ऊपर और नीचे कूदेंगे और एक ही रन के भीतर डेटा (एक रिपोर्ट) संगत नहीं होगा (उदाहरण के लिए योग डेबिट! = योग क्रेडिट)। आपके उपयोगकर्ता रिपोर्ट में विश्वास खो देंगे क्योंकि यह यादृच्छिक डेटा उत्पन्न करेगा। क्या आपने ['SNAPSHOT'] (http://msdn.microsoft.com/en-us/library/ms345124 (v = sql.90) .aspx) को इसके बजाय माना है? –

उत्तर

5

एक और दृष्टिकोण जारी करने के लिए, कनेक्शन के खिलाफ हो सकता है। या आप अपनी क्वेरी में टेबल पर WITH(NOLOCK) संकेत का उपयोग कर सकते हैं, जिसका कनेक्शन कनेक्शन को बदलने का लाभ नहीं है।

महत्वपूर्ण रूप से, ध्यान दें कि (असामान्य रूप से): तथापि यह हो जाता है बदल (लेन-देन, लेन-देन गुंजाइश, स्पष्ट SET, आदि), अलगाव स्तर नहीं समान ही अंतर्निहित कनेक्शन का उपयोग करता है के बीच रीसेट किया जाता है पूल से इसे लाने के दौरान। इसका मतलब यह है अपने कोड अलगाव स्तर (प्रत्यक्ष या परोक्ष) को परिवर्तित करता है, तो अपने कोड की कोई भी जानता है कि एक नए कनेक्शन के अलगाव के स्तर का है:

using(var conn = new SqlConnection(connectionString)) { 
    conn.Open(); 
    // isolation level here could be **ANYTHING**; it could be the default 
    // if it is a brand new connection, or could be whatever the last 
    // connection was when it finished 
} 

कौन सा WITH(NOLOCK) काफी आकर्षक बना देता है।

+0

.... आपके सुझावों की बहुत छोटी व्याख्याएं। – ulrichb

+1

वाह, अलगाव स्तर को स्थापित करने के बारे में चेतावनी के लिए धन्यवाद ... जो खतरनाक हो सकता है। –

+0

BeginTransaction के माध्यम से अलगाव स्तर सेट करके, क्या हम "अलगाव स्तर कनेक्शन के बीच रीसेट नहीं करते हैं" समस्या से बचते हैं? यदि हां, तो क्या लेनदेन का उपयोग करने में कोई कमी है? – digEmAll

1

मैं मार्क के साथ सहमत हैं, लेकिन वैकल्पिक रूप से आप प्रभावित टेबल पर NOLOCK क्वेरी संकेत इस्तेमाल कर सकते हैं। यह आपको टेबल स्तर से तालिका पर इसे नियंत्रित करने की क्षमता देगा।

साझा ताले लेने के बिना किसी भी प्रश्न चल साथ समस्या यह है कि आप अपने आप को "गैर नियतात्मक" परिणाम के लिए खुला छोड़ देते हैं, और व्यापार निर्णयों इस डेटा पर नहीं किया जाना चाहिए।

एक बेहतर दृष्टिकोण या तो परिदृश्य या किसी READ_COMMITED_SNAPSHOT अलगाव के स्तर की जांच के लिए हो सकता है। ये आपको ताले लेने के बिना लेनदेन संबंधी विसंगतियों के खिलाफ सुरक्षा देते हैं। व्यापार बंद यह है कि वे TempDB के खिलाफ आईओ बढ़ाते हैं। इनमें से किसी भी स्तर को या तो सत्र में लागू किया जा सकता है क्योंकि मार्क ने सुझाव दिया था या जैसा कि मैंने सुझाव दिया था।

आशा इस