2010-01-12 13 views
8

मैं मूल रूप से एक पंक्ति पर एक म्यूटएक्स अनुकरण करने के लिए MySQL पंक्ति लॉकिंग का उपयोग करने का प्रयास कर रहा हूं। आइए कहें कि मेरी तालिका में 2 कॉलम, एक आईडी और एक टेक्स्ट फ़ील्ड है, और तीन प्रविष्टियां (1, ए) (2, बी) और (3, सी) हैं। तालिका से चुनें; इन परिणामों को वापस कर देगा। मैं एक सामान्य पंक्ति को सामान्य तरीके से लॉक कर सकता हूं।जानबूझकर एक MySQL पंक्ति को कैसे लॉक करें जैसे कि SELECT भी एक त्रुटि लौटाएगा?

START TRANSACTION; 
BEGIN; 
SELECT * FROM table WHERE id = '2' FOR UPDATE; 

हालांकि, यदि दूसरे कनेक्शन से मैं तालिका से * चयन करना था। यह सभी 3 परिणाम वापस कर देगा। क्या लॉक लॉक होने वाली पंक्ति को देखने/उपयोग करने से मूल रूप से किसी भी चयन को रोकने के लिए पंक्ति स्तर लॉकिंग का कोई तरीका है? असल में मैं किसी को उस पंक्ति का उपयोग करने से रोकने की कोशिश कर रहा हूं जिसका वर्तमान में उपयोग किया जा रहा है/छेड़छाड़ की जा रही है, या यहां तक ​​कि पंक्ति को इसके डेटा के रूप में भी देख रहा है (क्योंकि इसका उपयोग/उपयोग किया जा रहा है) को चयन के समय सटीक होने पर भरोसा नहीं किया जा सकता ।

उत्तर

0

मुझे नहीं पता कि मूल करने के लिए कोई मूल, लॉकिंग विशिष्ट तंत्र है, लेकिन मेरा पहला इंस्टॉलेशन टेबल को स्थिति कॉलम (उदा। locked) देना होगा और पंक्ति को लॉक करते समय 1 पर सेट करना होगा। इसके select इसके प्रति संवेदनशील होने पर हमेशा किसी भी प्रश्न के लिए WHERE locked != '1' स्थिति जोड़ दी जाएगी।

एक तरफ ध्यान दें, मुझे नहीं पता कि आप क्या कर रहे हैं, लेकिन क्या यह ऐसा कार्य नहीं है जिसे डेटाबेस इंजन के ऊपर एक या दो स्तर किया जाना चाहिए?

+0

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

5

आप SERIALIZABLE लेनदेन अलगाव स्तर सेट करते हैं, InnoDB Wil implicity सभी SELECT बयान करने के लिए LOCK IN SHARE MODE जोड़ देते हैं।

यह मोड SELECT FOR UPDATE द्वारा रखे गए ताले के साथ संघर्ष करता है और SELECT एस लॉक हो जाएगा।

नोट, हालांकि, InnoDBWHERE स्थिति को संतुष्ट करने से अधिक पंक्तियों को लॉक कर सकता है। ऐसा इसलिए है क्योंकि यह सभी पंक्तियों को स्कैन किया गया स्कैन करता है, न केवल मिलान

SELECT * 
FROM mytable 
WHERE col1 = 1 
     AND col2 = 2 
FOR UPDATE 

इस सूचकांक का उपयोग करता है:

कहो, आप col1 पर एक सूचकांक और इस क्वेरी की है।

यह col2 <> 2

2

साथ यहां तक ​​कि उन वास्तव में, पंक्ति डेटा यहाँ तक कि जब आप इसे जोड़ तोड़ कर रहे हैं भरोसा किया जा सकता col1 = 1 साथ सभी रिकॉर्ड लॉक हो जाएगा।

यदि आप एक कनेक्शन से लेनदेन शुरू करते हैं, तो अन्य कनेक्शन लेनदेन करने तक आपके किसी भी बदलाव को नहीं देख पाएंगे।

5

आपको LOCK IN SHARE MODE की आवश्यकता है। SELECT गारंटी के साथ इसका उपयोग किसी और को FOR UPDATE के साथ किसी भी पंक्ति को लॉक कर रहा है।

उदा।

ग्राहक एक SELECT * FROM table WHERE type=2 FOR UPDATE

ग्राहक बी SELECT * FROM table LOCK IN SHARE MODE करता है और यहाँ लटका हुआ करता

ग्राहक एक लिखता है/आवेषण/अपडेट कुछ तो अब अन-फ्रीज़ एक COMMIT

ग्राहक बी करता है और प्रसंस्करण

शुरू
संबंधित मुद्दे