अद्यतन के लिए कब ... का उपयोग करें?


119

कृपया उपयोग के मामले को समझने में मेरी मदद करें SELECT ... FOR UPDATE

प्रश्न 1 : निम्नलिखित का एक अच्छा उदाहरण है कि कब SELECT ... FOR UPDATEइस्तेमाल किया जाना चाहिए?

दिया हुआ:

  • कमरे [id]
  • टैग [आईडी, नाम]
  • Room_tags [room_id, tag_id]
    • Room_id और tag_id विदेशी कुंजी हैं

एप्लिकेशन सभी कमरों और उनके टैगों को सूचीबद्ध करना चाहता है, लेकिन जिन कमरों को हटाया नहीं गया है, उन सभी कमरों के बीच अंतर करने की आवश्यकता है। यदि चयन ... के लिए अद्यतन का उपयोग नहीं किया जाता है, तो क्या हो सकता है:

  • प्रारंभ में:
    • कमरे शामिल हैं [id = 1]
    • टैग शामिल हैं [id = 1, name = 'cats']
    • Room_tags शामिल हैं [room_id = 1, tag_id = 1]
  • धागा 1: SELECT id FROM rooms;
    • returns [id = 1]
  • धागा 2: DELETE FROM room_tags WHERE room_id = 1;
  • धागा 2: DELETE FROM rooms WHERE id = 1;
  • धागा 2: [लेन-देन करता है]
  • धागा 1: SELECT tags.name FROM room_tags, tags WHERE room_tags.tag_id = 1 AND tags.id = room_tags.tag_id;
    • खाली सूची देता है

अब थ्रेड 1 सोचता है कि कमरे 1 में कोई टैग नहीं है, लेकिन वास्तव में कमरा हटा दिया गया है। इस समस्या को हल करने के लिए, थ्रेड 1 चाहिए SELECT id FROM rooms FOR UPDATE, जिससे थ्रेड 2 को roomsथ्रेड 1 होने तक हटाने से रोका जा सके । क्या वो सही है?

प्रश्न 2 : जब एक का उपयोग करना चाहिए SERIALIZABLEबनाम लेनदेन अलगाव READ_COMMITTEDके साथ SELECT ... FOR UPDATE?

उत्तर पोर्टेबल (डेटाबेस-विशिष्ट नहीं) होने की उम्मीद है। यदि यह संभव नहीं है, तो कृपया इसकी व्याख्या करें।


2
आप कौन से RDBMS का उपयोग कर रहे हैं?
क्वासोई

2
@Quassnoi, जैसा कि प्रश्न के नीचे उल्लेख किया गया है, मैं एक पोर्टेबल (डेटाबेस-विशिष्ट नहीं) समाधान की तलाश कर रहा हूं।
गिल्ली

2
क्या विकल्प REPEATABLE_READऔर READ_COMMITTEDयहां तक ​​कि पोर्टेबल विकल्प भी हैं? केवल उन परिणामों के लिए जो मैं प्राप्त करता हूं, वे MSSQL सर्वर के लिए हैं
बिली ओनली

3
@ बिलियन: ध्यान दें कि आइसोलेशन मोड यह गारंटी देते हैं कि आप उन quirks को नहीं देखते हैं जो वे अनुमति नहीं देते हैं, लेकिन वे उन quirks के बारे में कुछ नहीं कहते हैं जो वे अनुमति देते हैं। इसका मतलब यह है कि सेटिंग, कहते हैं, READ COMMITTEDमोड यह परिभाषित नहीं करता है कि आप वास्तव में किसी अन्य लेनदेन द्वारा किए गए रिकॉर्ड देखेंगे या नहीं: यह केवल यह सुनिश्चित करता है कि आप बिना रिकॉर्ड किए गए रिकॉर्ड कभी नहीं देखेंगे।
क्वासोइ

3
एक select ... for updateपर roomsअभी भी अनुमति होगी room_tags, क्योंकि वे अलग-अलग तालिकाओं हैं हटाए जाने के लिए। क्या आपके कहने का मतलब यह है कि क्या इस for updateखंड को हटाने से रोका जाएगा rooms?
क्रिस सैक्सन

जवाबों:


84

कमरे और टैग के बीच निरंतरता प्राप्त करने का एकमात्र पोर्टेबल तरीका और सुनिश्चित करने के बाद कमरे कभी भी वापस नहीं आते हैं क्योंकि उन्हें हटा दिया गया था, उन्हें लॉक कर रहा है SELECT FOR UPDATE

हालाँकि कुछ प्रणालियों में ताला लगाना संगामिति नियंत्रण का एक दुष्प्रभाव है, और आप FOR UPDATEस्पष्ट रूप से निर्दिष्ट किए बिना समान परिणाम प्राप्त करते हैं ।


इस समस्या को हल करने के लिए, थ्रेड 1 चाहिए SELECT id FROM rooms FOR UPDATE, जिससे थ्रेड 2 को roomsथ्रेड 1 होने तक हटाने से रोका जा सके । क्या वो सही है?

यह आपके डेटाबेस सिस्टम का उपयोग कर रही संगणना नियंत्रण पर निर्भर करता है।

  • MyISAMमें MySQL(और कई अन्य पुराने सिस्टम) एक प्रश्न की अवधि के लिए पूरी तालिका लॉक करता है।

  • प्रश्नों में SQL Server, SELECTसाझा किए गए रिकॉर्ड्स / पृष्ठों / तालिकाओं पर साझा किए गए लॉक को जगह देता है, जबकि DMLक्वेरीज़ अपडेट लॉक (जो बाद में अनन्य या पदोन्नत किए गए साझा ताले को प्राप्त होते हैं) को स्थान देते हैं। विशिष्ट ताले साझा किए गए ताले के साथ असंगत हैं, इसलिए या तो SELECTया DELETEसत्र दूसरे सत्र के शुरू होने तक लॉक हो जाएगा।

  • डेटाबेस में जो उपयोग करते हैं MVCC(जैसे Oracle, PostgreSQLके MySQLसाथ InnoDB), एक DMLक्वेरी रिकॉर्ड की एक प्रतिलिपि बनाता है (एक या दूसरे तरीके से) और आमतौर पर पाठक लेखकों को ब्लॉक नहीं करते हैं और इसके विपरीत। इन डेटाबेस के लिए, एक SELECT FOR UPDATEकाम आएगा: यह SELECTया तो या DELETEक्वेरी को तब तक लॉक करेगा , जब तक कि दूसरा सत्र शुरू SQL Serverनहीं हो जाता।

जब एक का उपयोग करना चाहिए REPEATABLE_READबनाम लेनदेन अलगाव READ_COMMITTEDके साथ SELECT ... FOR UPDATE?

आम तौर पर, REPEATABLE READप्रेत पंक्तियों को संशोधित नहीं किया जाता (पंक्तियाँ जो संशोधित होने के बजाय किसी अन्य लेनदेन में दिखाई या गायब हो जाती हैं)

  • में Oracleऔर पहले के PostgreSQLसंस्करण, REPEATABLE READवास्तव में एक पर्यायवाची हैं SERIALIZABLE। मूल रूप से, इसका मतलब है कि लेनदेन शुरू होने के बाद किए गए परिवर्तनों को नहीं देखता है। इसलिए इस सेटअप में, अंतिम Thread 1क्वेरी कमरे में वापस आ जाएगी जैसे कि इसे कभी भी हटाया नहीं गया है (जो आप चाहते थे या नहीं हो सकता है)। यदि आप हटाए जाने के बाद कमरों को नहीं दिखाना चाहते हैं, तो आपको पंक्तियों को लॉक करना चाहिएSELECT FOR UPDATE

  • में InnoDB, REPEATABLE READऔर SERIALIZABLEअलग-अलग चीजें हैं: SERIALIZABLEमोड में पाठकों ने उन रिकॉर्डों पर अगले-कुंजी ताले लगाए, जो वे मूल्यांकन करते हैं, प्रभावी रूप DMLसे उन पर समवर्ती को रोकते हैं। तो आप SELECT FOR UPDATEक्रमिक मोड में एक की जरूरत नहीं है, लेकिन उन्हें REPEATABLE READया में की जरूरत है READ COMMITED

ध्यान दें कि आइसोलेशन मोड पर मानक यह निर्धारित करता है कि आप अपने प्रश्नों में कुछ क्वैर नहीं देखते हैं लेकिन यह परिभाषित नहीं करते हैं कि (लॉकिंग के साथ MVCCया अन्यथा) कैसे।

जब मैं कहता हूं "आपको कुछ ज़रूरत नहीं है SELECT FOR UPDATE" मुझे कुछ डेटाबेस इंजन कार्यान्वयन के दुष्प्रभावों के कारण "मुझे वास्तव में जोड़ना चाहिए"।


1
अंतिम बिंदु इस मामले की जड़ है, मुझे लगता है: "आपको धारावाहिक मोड में अद्यतन के लिए चयन की आवश्यकता नहीं है, लेकिन उन्हें READATABLE READ या READ COMMITED में आवश्यकता है"।
कॉलिन टी हार्ट

आप सही हे। दूसरा सवाल यह पूछे जाने पर किया जाना चाहिए था SERIALIZABLEबनाम इस्तेमाल किया जाना चाहिए READ_COMMITTEDके साथ SELECT ... FOR UPDATE। क्या आप इस अद्यतन प्रश्न को दर्शाने के लिए अपने उत्तर को अपडेट कर सकते हैं?
गिल्ली

1
@ गिलि: "आपको SELECT FOR UPDATEक्रमिक मोड में" की आवश्यकता नहीं है InnoDB। अन्य MVCCप्रणालियों के साथ, दो पर्यायवाची हैं और आपको आवश्यकता है SELECT FOR UPDATE
क्वासोई

1
मुझे लगता है कि कॉलिन की पोस्ट मेरे विशिष्ट प्रश्नों के उत्तर आपके उत्तर से बेहतर है लेकिन मैं आपके द्वारा दिए गए सभी संदर्भों की सराहना करता हूं। मैं एक उत्तर को स्वीकार करूंगा जो दो को मिलाता है (शीर्ष पर विशिष्ट उत्तर, नीचे दिए गए संदर्भों का समर्थन करता है)।
गिल्ली

This depends on the concurrency control your database system is using: मुझे लगता है कि तुम बाल बंट रहे हो। आपके द्वारा नीचे सूचीबद्ध सभी मामलों का कहना है कि SELECTलेनदेन के अंत के बीच कमरा नहीं हटाया गया है । तो, क्या उत्तर केवल Yesसहायक संदर्भों के साथ नहीं होना चाहिए ?
गिल्ली

33

छोटे जवाब:

Q1: हाँ।

Q2: कोई फर्क नहीं पड़ता जो आप का उपयोग करें।

लंबा जवाब:

एक select ... for updateवसीयत (जैसा कि इसका तात्पर्य है) कुछ पंक्तियों का चयन करती है, लेकिन उन्हें लॉक भी करती है जैसे कि उन्हें पहले से ही वर्तमान लेनदेन द्वारा अपडेट किया गया है (या जैसे कि पहचान अपडेट किया गया था)। यह आपको वर्तमान लेनदेन में उन्हें फिर से अपडेट करने और फिर प्रतिबद्ध करने की अनुमति देता है, बिना किसी अन्य लेनदेन के इन पंक्तियों को किसी भी तरह से संशोधित करने में सक्षम है।

इसे देखने का एक और तरीका है, यह ऐसा है जैसे निम्नलिखित दो बयानों को परमाणु रूप से निष्पादित किया जाता है:

select * from my_table where my_condition;

update my_table set my_column = my_column where my_condition;

चूँकि इससे प्रभावित पंक्तियाँ my_conditionलॉक हो जाती हैं, इसलिए कोई भी अन्य लेन-देन उन्हें किसी भी तरह से संशोधित नहीं कर सकता है, और इसलिए, लेन-देन अलगाव स्तर से यहाँ कोई अंतर नहीं पड़ता है।

यह भी ध्यान दें कि लेन-देन अलगाव स्तर लॉकिंग से स्वतंत्र है: एक अलग आइसोलेशन स्तर सेट करना आपको किसी अन्य लेन-देन में पंक्तियों को लॉक करने और अद्यतन करने की अनुमति नहीं देता है जो आपके लेनदेन द्वारा लॉक किए जाते हैं।

लेन-देन अलगाव स्तर क्या गारंटी देते हैं (विभिन्न स्तरों पर) लेनदेन की प्रगति के दौरान डेटा की स्थिरता होती है।


1
मुझे लगता What transaction isolation levels do guarantee [...] is the consistency of data once transactions are completed.है कि गलत तरीके से इसका मतलब है कि एक लेनदेन के दौरान अलगाव का स्तर प्रभावित नहीं होता है । मैं इस खंड को संशोधित करने और लेन-देन के दौरान आपके द्वारा देखे जाने (या न देखने) के प्रभावों के बारे में अधिक विवरण प्रदान करने की सलाह देता हूं।
गिल्ली

1
मुझे लगता है कि आपकी पोस्ट मेरे विशिष्ट सवालों के जवाब क्वासोई से बेहतर है, लेकिन मैं उनके द्वारा दिए गए सभी संदर्भों की सराहना करता हूं। मैं एक उत्तर को स्वीकार करूंगा जो दो को मिलाता है (शीर्ष पर विशिष्ट उत्तर, नीचे दिए गए संदर्भों का समर्थन करता है)।
गिल्ली

लॉकिंग और अलगाव परस्पर जटिल हैं। तो क्या उस बारे में ज्ञान प्राप्त करने के लिए कोई किताबें हैं?
चाओ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.