SQL आवेषण कैसे प्राप्त करें और / या MS SQL सर्वर पर पूरी तालिका को लॉक न करने के लिए अपडेट करें


13

DB काम पर बहुत नौसिखिया, इसलिए एक बुनियादी सवाल के साथ अपने धैर्य की सराहना करें। मैं अपने स्थानीय मशीन पर SQL सर्वर 2014 चला रहा हूं, और मेरे पास अलग-अलग तरीकों का परीक्षण करने के लिए एक छोटी सी मेज और एक बुनियादी क्लाइंट एप्लिकेशन है। मुझे लग रहा है कि दोनों INSERT INTOऔर UPDATEबयानों के दौरान टेबल लॉक होना क्या प्रतीत होता है । ग्राहक निम्नलिखित कोड के साथ एक ASP.NET अनुप्रयोग है:

OleDbConnection cn = new OleDbConnection("Provider=SQLNCLI11; server=localhost\\SQLEXPRESS; Database=<my db>; user id=<my uid>; password=<my pwd>");
cn.Open();
OleDbTransaction tn = cn.BeginTransaction();
OleDbCommand cmd = new OleDbCommand("INSERT INTO LAYOUTSv2 (LAYOUTS_name_t, LAYOUTS_enabled_b, LAYOUTS_data_m) VALUES ('name', '-1', 'data')", cn, tn);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
int newkey = Decimal.ToInt32((decimal)cmd.ExecuteScalar());
Console.WriteLine("Created index " + newkey);
Thread.Sleep(15000);
tn.Commit();
tn = cn.BeginTransaction();
cmd.CommandText = "UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key='" + newkey + "'";
cmd.Transaction = tn;
cmd.ExecuteNonQuery();
Console.WriteLine("updated row");
Thread.Sleep(15000);
tn.Rollback();
cn.Close();

मैं इस कोड को चलाता हूं, फिर प्रबंधन स्टूडियो से चलाता हूं SELECT * FROM LAYOUTSv2। दोनों मामलों के दौरान जब क्लाइंट थ्रेड को रोक दिया जाता है (यानी कमिट / रोलबैक से पहले) सेलेक्ट क्वेरी तब तक लटकती है जब तक कि कमिट / रोलबैक न हो जाए।

तालिका में प्राथमिक कुंजी के रूप में निर्दिष्ट LAYOUTS_key फ़ील्ड है। प्रॉपर्टीज विंडो में यह पता चलता है कि यह अद्वितीय और क्लस्टर है, जिसमें पेज लॉक और पंक्ति लॉक दोनों की अनुमति है। तालिका के लिए लॉक एस्केलेशन सेटिंग अक्षम है ... मैंने बिना किसी परिवर्तन के तालिका और ऑटो की दोनों अन्य उपलब्ध सेटिंग्स की कोशिश की है। मैंने कोशिश की है SELECT ... WITH (NOLOCK)और वह तुरंत एक परिणाम देता है, लेकिन जैसा कि यहां और अन्य स्थानों पर अच्छी तरह से चेतावनी दी गई है, यह वह नहीं है जो मुझे करना चाहिए। मैं ROWLOCKदोनों INSERTऔर UPDATEबयानों पर संकेत डालने की कोशिश की है , लेकिन कुछ भी नहीं बदला है।

मैं जिस व्यवहार की तलाश कर रहा हूं वह यह है: एक प्रतिबद्ध होने से पहले INSERT, अन्य थ्रेड्स के क्वेरीज़ INSERTएड को छोड़कर सभी पंक्तियों को पढ़ते हैं । UPDATEअन्य थ्रेड्स की क्वेरी करने से पहले पंक्ति के आरंभिक संस्करण को UPDATEएड किया जाना पढ़ें । क्या कोई और तरीका है इसे करने के लिए? अगर मुझे अपने उपयोग के मामले को स्पष्ट करने के लिए अन्य जानकारी प्रदान करने की आवश्यकता है तो कृपया मुझे बताएं। धन्यवाद।


3
वैसे WHERE LAYOUTS_key='" + newkey + "', SQL इंजेक्शन सहित विभिन्न कारणों के लिए एक पूर्ण नहीं-नहीं है, आपको पैरामीटर प्रश्नों का उपयोग करना चाहिए।
मार्टिन स्मिथ

1
@MartinSmith इस पर सिर के लिए धन्यवाद ... या तो पैरामीटर किए गए प्रश्नों या SQL इंजेक्शन हमलों के बारे में कभी नहीं सुना।
जॉन रिहाल

@JohnRiehl, फिर से: इंजेक्शन के हमले, कल्पना करें कि आपका उपयोगकर्ता newkey" something';DELETE FROM LAYOUTSv2 --" पर सेट होता है । आपका अपडेट सफलतापूर्वक पूरा हो जाएगा, और फिर तालिका को खाली कर दें क्योंकि उपयोगकर्ता ने एपोस्ट्रोफ डालकर क्वेरी को हेरफेर किया था। आम तौर पर, एक पैरामीटर की गई क्वेरी कुछ ऐसी दिखती है UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?, जिसके बाद आप ?अपने कोड में अलग से मान (ओं) को (पैरामीटर) असाइन करते हैं।
डैनियल हतमाचर

जवाबों:


10

संभावना है कि यह "पूरी तालिका" को लॉक नहीं कर रहा है।

यह तालिका में एक पंक्ति को लॉक कर रहा है, लेकिन आपका SELECT * FROM LAYOUTSv2प्रयास पूरी तालिका को पढ़ने की कोशिश करता है ताकि आवश्यक रूप से उस लॉक को अवरुद्ध कर दिया जाए।

डालने के मामले के लिए आप केवल READPASTबंद पंक्ति को छोड़ने के संकेत को निर्दिष्ट कर सकते हैं- हालाँकि जो UPDATEमामले के लिए आपका वांछित परिणाम नहीं देगा (यह पंक्ति को फिर से छोड़ देगा पंक्ति के शुरुआती संस्करण को नहीं पढ़ता है)।

यदि आप पढ़े गए स्नैपशॉट अलगाव के लिए डेटाबेस को कॉन्फ़िगर करते हैं तो यह दोनों मामलों के लिए आपका वांछित प्रभाव देगा (अधिक से अधिक उपयोग की कीमत पर tempdb)


मैंने "इज़ रीड कमिटेड स्नैपशॉट ऑन" को ट्रू में बदल दिया और अब यह पूरी तरह से काम करता है जिसमें कोई संकेत नहीं चाहिए। धन्यवाद! एक अनुवर्ती ... मैंने झूठी अनुमति के लिए "स्नैपशॉट अलगाव" की अनुमति छोड़ दी ... क्या यह ठीक है? धन्यवाद।
जॉन रिहाल

@ जोहानिएहल - हाँ यदि आप स्पष्ट रूप से SNAPSHOTअलगाव का उपयोग नहीं कर रहे हैं तो इसे निष्क्रिय छोड़ दें और फिर इसे सक्षम करें यदि आप बाद में तय करते हैं कि यह आपके लिए उपयोगी होगा।
मार्टिन स्मिथ

7

इन्सर्ट और अपडेट स्टेटमेंट को पंक्ति-स्तरीय ताले बनाने के लिए माना जाता है। हालाँकि, जब किसी लेन-देन में तालों की संख्या 5,000 या उससे अधिक होती है तो एक ताला बढ़ जाता है और यह एक टेबल लेवल लॉक बनाता है। कृपया नीचे देखे।

https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx


इस प्रश्न के लिए प्रासंगिक नहीं है क्योंकि INSERT और UPDATE दोनों कथन एक पंक्ति में लिख रहे हैं
मार्टिन स्मिथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.