MySQL
चुनें ... अद्यतन के साथ अद्यतन के लिए
InnoDB (ऑटो-कमिट बंद) के साथ लेन-देन का उपयोग करना, एक SELECT ... FOR UPDATE
एक सत्र को किसी विशेष रिकॉर्ड (या रिकॉर्ड) को अस्थायी रूप से लॉक करने की अनुमति देता है ताकि कोई अन्य सत्र इसे अपडेट न कर सके। फिर, उसी लेन-देन के भीतर, सत्र वास्तव में एक UPDATE
प्रदर्शन कर सकता है उसी रिकॉर्ड पर और लेनदेन को प्रतिबद्ध या वापस रोल करें। यह आपको रिकॉर्ड को लॉक करने की अनुमति देगा ताकि कोई अन्य सत्र इसे अपडेट न कर सके, जबकि शायद आप कुछ अन्य व्यावसायिक तर्क करते हैं।
यह लॉकिंग के साथ पूरा किया जाता है। InnoDB रिकॉर्ड को लॉक करने के लिए इंडेक्स का उपयोग करता है, इसलिए मौजूदा रिकॉर्ड को लॉक करना आसान लगता है - बस उस रिकॉर्ड के लिए इंडेक्स को लॉक करें।
चुनें ... INSERT के साथ अपडेट के लिए
हालांकि, उपयोग करने के लिए SELECT ... FOR UPDATE
INSERT
. के साथ , आप किसी ऐसे रिकॉर्ड के लिए इंडेक्स को कैसे लॉक करते हैं जो अभी तक मौजूद नहीं है? यदि आप REPEATABLE READ
. के डिफ़ॉल्ट आइसोलेशन स्तर का उपयोग कर रहे हैं , InnoDB गैप . का भी उपयोग करेगा ताले जब तक आप id
. जानते हैं (या आईडी की रेंज भी) लॉक करने के लिए, फिर InnoDB गैप को लॉक कर सकता है ताकि उस गैप में कोई अन्य रिकॉर्ड तब तक नहीं डाला जा सके जब तक कि हम इसके साथ काम नहीं कर लेते।
अगर आपका id
कॉलम एक ऑटो-इन्क्रीमेंट कॉलम था, फिर SELECT ... FOR UPDATE
INSERT INTO
. के साथ समस्याग्रस्त होगा क्योंकि आपको नहीं पता होगा कि नया id
क्या है जब तक आप इसे सम्मिलित नहीं करते थे। हालाँकि, चूंकि आप id
जानते हैं जिसे आप सम्मिलित करना चाहते हैं, SELECT ... FOR UPDATE
INSERT
. के साथ काम करेगा।
चेतावनी
डिफ़ॉल्ट आइसोलेशन स्तर पर, SELECT ... FOR UPDATE
गैर-मौजूद रिकॉर्ड पर नहीं अन्य लेनदेन को रोकें। इसलिए, यदि दो लेन-देन दोनों एक करते हैं SELECT ... FOR UPDATE
एक ही गैर-मौजूद इंडेक्स रिकॉर्ड पर, वे दोनों लॉक प्राप्त करेंगे, और न ही लेनदेन रिकॉर्ड को अपडेट करने में सक्षम होंगे। वास्तव में, यदि वे कोशिश करते हैं, तो एक गतिरोध का पता चल जाएगा।
इसलिए, यदि आप गतिरोध से निपटना नहीं चाहते हैं, तो आप बस निम्न कार्य कर सकते हैं:
इसमें डालें ...
लेन-देन शुरू करें, और INSERT
निष्पादित करें . अपना व्यावसायिक तर्क करें, और या तो लेन-देन करें या रोलबैक करें। जैसे ही आप INSERT
करते हैं पहले लेन-देन पर गैर-मौजूद रिकॉर्ड अनुक्रमणिका पर, अन्य सभी लेन-देन ब्लॉक हो जाएंगे यदि वे INSERT
करने का प्रयास करते हैं एक ही अद्वितीय सूचकांक के साथ एक रिकॉर्ड। यदि पहला लेनदेन सम्मिलित करने के बाद दूसरा लेनदेन उसी सूचकांक के साथ एक रिकॉर्ड डालने का प्रयास करता है, तो उसे "डुप्लिकेट कुंजी" त्रुटि मिलेगी। तदनुसार संभालें।
चुनें ... शेयर मोड में लॉक करें
यदि आप LOCK IN SHARE MODE
. के साथ चयन करते हैं INSERT
. से पहले , यदि पिछले लेन-देन ने वह रिकॉर्ड डाला है लेकिन अभी तक प्रतिबद्ध नहीं किया है, तो SELECT ... LOCK IN SHARE MODE
पिछला लेन-देन पूरा होने तक अवरुद्ध रहेगा।
इसलिए डुप्लीकेट कुंजी त्रुटियों की संभावना को कम करने के लिए, विशेष रूप से यदि आप व्यापार तर्क करने या उन्हें वापस रोल करने से पहले कुछ समय के लिए ताले को पकड़ते हैं:
-
SELECT bar FROM FooBar WHERE foo = ? LOCK FOR UPDATE
- यदि कोई रिकॉर्ड नहीं लौटा, तो
INSERT INTO FooBar (foo, bar) VALUES (?, ?)
में डालें