थ्रेड-सुरक्षित तरीके से एक मान (काउंटर) को क्वेरी और कैसे बढ़ाएं? (दौड़ की स्थिति से बचें)


10

एक तालिका में जहां प्रत्येक पंक्ति में एक काउंटर (सिर्फ एक पूर्णांक मान) होता है, मुझे वर्तमान मूल्य प्राप्त करने और उसी समय इसे बढ़ाने की आवश्यकता होती है ।

प्रभावी रूप से, मैं यह करना चाहता हूं:

SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123

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

मैं एक निर्माण के बारे में सोच सकता हूं जहां मैं प्रति पंक्ति एक मैनुअल लॉक लागू करता हूं, लेकिन मुझे आश्चर्य है कि क्या ऐसा करने का एक आसान तरीका है?


लेनदेन का उपयोग कर रहे हैं?
ypercube y

जवाबों:


15

अपडेट स्टेटमेंट पहले के चयन के बिना पूरी तरह से ठीक काम करता है! चूँकि एकल कथन परिभाषा द्वारा सुरक्षित हैं, यहाँ तक कि एक ही समय में किए गए दो अद्यतन प्रश्नों का परिणाम केवल पंक्ति में दो बार होगा।

यदि आप वास्तव में अपने PHP स्क्रिप्ट के लिए मूल्य का चयन करना चाहते हैं, तो इसके साथ कुछ करें और बाद में इस सटीक काउंटर मूल्य को अपडेट करना चाहते हैं, तो आप निम्न कर सकते हैं:

BEGIN;
SELECT `counter` FROM `table` WHERE `id` = 123 FOR UPDATE;
UPDATE `table` SET `counter` = `counter`+1 WHERE `id` = 123;
COMMIT;

यह एक नया लेनदेन शुरू करता है, फिर उन पंक्तियों का चयन करता है जिन्हें आप अपडेट करना चाहते हैं और उन्हें विशेष रूप से लॉक करते हैं। फिर आप सुरक्षित रूप से उन अन्य ग्राहकों की चिंता किए बिना उनकी सामग्री को बदलने या यहां तक ​​कि बंद पंक्तियों तक पहुंचने के बारे में अपडेट कर सकते हैं। अंत में आपको अपने परिवर्तन करने की आवश्यकता है।

आपको आइसोलेशन लेवल के बारे में भी कुछ पढ़ना चाहिए । आप संभावना नहीं चाहते हैं READ UNCOMMITTEDकि आइसोलेशन स्तर जैसा कोई मान हो । इस उपयोग के मामले में बाकी सब कुछ ठीक होना चाहिए।


मैंने अन्य स्थानों पर पढ़ा कि UPDATE table SET counter = counter + 1पर्याप्त परमाणु है? क्या आपको अभी भी लेन-देन के बयानों की आवश्यकता है?
CMCDragonkai

@CMCDragonkai आपकी क्वेरी अकेले परमाणु है, लेकिन यदि आप पहले मूल्य का चयन करते हैं FOR UPDATEऔर उपयोग नहीं करते हैं और लेनदेन करते हैं, तो आपके द्वारा चयनित मूल्य अपडेट क्वेरी में उपयोग किए गए से भिन्न हो सकता है। मेरे प्रश्नों का संयोजन मान के चयनित होते ही पंक्ति को लॉक कर देता है और इसलिए यह सुनिश्चित करता है कि इस सटीक काउंटर वैल्यू का उपयोग अपडेट क्वेरी में किया जाएगा।
घोस्टबलर

ठीक है, लेकिन यह केवल आवश्यक है अगर मैं सही वृद्धि के अलावा कोई काम करता हूं? जैसा कि यह खड़ा है, एक अकेला परमाणु अद्यतन क्वेरी काफी अच्छा है अगर वह सब करना चाहता है?
CMCDragonkai

1
@CMCDragonkai यदि आप किसी अन्य क्वेरी को निष्पादित नहीं करते हैं जो कॉलम को छूती है, तो आप अच्छे हैं।
घोस्टगैम्बलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.