2010-03-29 14 views
7

MySQL की लॉकिंग सुविधा के साथ मेरे पास एक अजीब समस्या है (कम से कम मेरे लिए :))। इस डेटा के साथअद्यतन के लिए MySQL चयन - अजीब समस्या

create table `test` ( 
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1 

:

मैं एक मेज है

+ ---- +
| आईडी |
+ ---- +
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 10 |
| 11 |
| 12 |
+ ---- +

अब मैं इन आदेशों शुरुआत में मार डाला के साथ 2 ग्राहक हैं:

सेट autocommit = 0;
सेट सत्र लेनदेन अलगाव स्तर serializable;
शुरू;

अब सबसे दिलचस्प हिस्सा है। पहला क्लाइंट इस क्वेरी को निष्पादित करता है: (आईडी के बराबर आईडी के साथ एक पंक्ति डालने का इरादा 9)

परीक्षण से चुनें जहां आईडी = 9 अद्यतन के लिए;
खाली सेट (0.00 सेकंड)

तो दूसरा ग्राहक एक ही करता है: परीक्षण से

चुनें * जहां आईडी = 9 अद्यतन के लिए;
खाली सेट (0.00 सेकंड)

मेरा प्रश्न है: क्यों दूसरा ग्राहक ब्लॉक नहीं करता? एक विशेष अंतर लॉक पहली क्वेरी द्वारा सेट किया जाना चाहिए क्योंकि अद्यतन के लिए उपयोग किया गया है और दूसरे क्लाइंट को ब्लॉक करना चाहिए।

यदि मैं गलत हूं, तो क्या कोई मुझे बता सकता है कि इसे सही तरीके से कैसे किया जाए?

MySQL संस्करण मैं का उपयोग करें: 5.1.37-1ubuntu5.1

+0

यह ब्लॉक नहीं करता है क्योंकि आपने सफलतापूर्वक ** शून्य ** पंक्तियों को लॉक कर दिया है। – Pacerier

उत्तर

3

क्योंकि उस समय, यह सुरक्षित है (खाली) परिणाम वापस जाने के लिए - वहाँ रिकार्ड के लिए सेट करने के लिए कोई लॉक है आईडी = 9 के साथ यह अस्तित्व में नहीं है और इस प्रकार इसे अपडेट नहीं किया जा सकता है - मुझे नहीं लगता कि आप इस तरह के मामले में एक पठित ताले लगाने के लिए innodb पर भरोसा कर सकते हैं। हालांकि आईडी = 9 पर लिखना लॉक सेट करना चाहिए।

यदि बाद में, लेनदेन में से एक तालिका तालिका को अद्यतन करता है, और उसी डेटा को दूसरे लेनदेन के रूप में स्पर्श करता है - तो अपडेट लेनदेन में से एक में अवरुद्ध हो जाएगा और बाद में अन्य लेनदेन उस डेटा को विफल कर देगा।इस तरह के परिदृश्यों में लेन-देन विफल होने के लिए यह बिल्कुल सामान्य है - आपको इसे संभालने के लिए छोड़कर - जो आम तौर पर लेनदेन को पुनः प्रयास करने का मामला है।

यदि आईडी = 9 के साथ रिकॉर्ड था तो आप शायद पहले लेनदेन समाप्त होने तक 2. select ब्लॉक देखेंगे, क्योंकि अब एक रिकॉर्ड है जिसे पहले लेनदेन को अद्यतन करने का निर्णय लेने के दौरान लॉक किया जाना है वह पंक्ति

+1

हां, यदि आईडी = 9 के साथ दूसरा चयन ब्लॉक है तो रिकॉर्ड। तो मुझे आईडी 9 को "आरक्षित" कैसे करना चाहिए? मुझे यह समस्या है क्योंकि मैं वस्तुओं के जोड़े के बीच कुछ संबंध संग्रहित कर रहा हूं और मुझे वस्तुओं की दी गई जोड़ी के लिए केवल एक पंक्ति चाहिए। –

+0

यह बताना मुश्किल है कि आप क्या करने की कोशिश कर रहे हैं। क्या आपके लेनदेन में से एक आईडी = 9 बनायेगा? इस मामले में अन्य लेनदेन विफल हो जाएंगे/वापस लुढ़क जाएंगे। – nos

+0

मैं जावा में इस तरह कुछ लागू करने की कोशिश कर रहा हूं: अगर (! RowExists (9)) { createRowWithId (9); } अन्य { वापसी "त्रुटि"; } और मुझे डुप्लीकेट आईडी मिल रही है ... –

संबंधित मुद्दे