कमरों और टैग के बीच एकरूपता प्राप्त करने और यह सुनिश्चित करने का एकमात्र पोर्टेबल तरीका है कि कमरे हटाए जाने के बाद कभी वापस न हों, उन्हें 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
query रिकॉर्ड की एक प्रति बनाता है (एक या दूसरे तरीके से) और आम तौर पर पाठक लेखकों को ब्लॉक नहीं करते हैं और इसके विपरीत। इन डेटाबेस के लिए, एक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
" मुझे वास्तव में "कुछ डेटाबेस इंजन कार्यान्वयन के दुष्प्रभावों के कारण" जोड़ना चाहिए था।