2010-11-05 5 views
6

मेरे पास एक सारणी है जो एक ही समय में विभिन्न धागे द्वारा पढ़ी जाती है।लॉक की गई पंक्ति को एक MySQL क्वेरी में अनदेखा करना

प्रत्येक थ्रेड को 100 पंक्तियों का चयन करना होगा, प्रत्येक पंक्ति पर कुछ कार्यों को निष्पादित करना होगा (डेटाबेस से संबंधित नहीं) तो उन्हें तालिका से चयनित पंक्ति को हटाना होगा।

SELECT id FROM table_name FOR UPDATE; 

मेरा प्रश्न है:: मैं कैसे अनदेखा कर सकते हैं (या छोड़ दें) पंक्तियों कि पहले MySQL में एक का चयन करें कथन का उपयोग बंद कर दिया गया

पंक्तियां इस क्वेरी का उपयोग कर चयन किया जाता है?

उत्तर

15

मैं आम तौर पर एक PROCESS_ID स्तंभ डिफ़ॉल्ट शून्य है कि बनाने और उसके बाद प्रत्येक थ्रेड एक अद्वितीय पहचानकर्ता का उपयोग निम्नलिखित क्या करना है:

UPDATE table_name SET process_id = #{process.id} WHERE process_id IS NULL LIMIT 100; 

SELECT id FROM table_name WHERE process_id = #{process.id} FOR UPDATE; 

कि सुनिश्चित करता है कि प्रत्येक थ्रेड मेज से पंक्तियों की एक अद्वितीय सेट का चयन करता है।

उम्मीद है कि इससे मदद मिलती है।

+1

+1 में मदद करता है आप LIMIT एक अच्छा विचार उपयोग कर रहा है –

+1

इस उदाहरण में स्क्रिप्ट अचानक पहले अपडेट के बाद निरस्त किया गया है, तो कैसे होगा आप "क्लीन"। पुरानी प्रक्रियाओं से डेटाबेस? अन्यथा उन 100 पंक्तियों का कभी भी ख्याल नहीं रखा जाएगा। –

+1

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

0

हालांकि यह सबसे अच्छा समाधान नहीं है, क्योंकि लॉक पंक्तियों को अनदेखा करने के लिए मुझे कोई रास्ता नहीं है, मैं एक यादृच्छिक एक चुनता हूं और लॉक प्राप्त करने का प्रयास करता हूं।

START TRANSACTION; 
SET @v1 =(SELECT myId FROM tests.table WHERE status is NULL LIMIT 1); 
SELECT * FROM tests.table WHERE [email protected] FOR UPDATE; #<- lock 

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

लेनदेन के बिना हर संभव संभावित समाधान (उदाहरण के लिए पंक्ति में कोई स्थिति नहीं है और ... आदि) आसानी से दौड़ की स्थिति और मिस्ड प्रक्रियाएं प्रदान कर सकती है (उदाहरण के लिए एक थ्रेड अचानक मर जाता है, आवंटित डेटा अभी भी टैग किया जाता है, जबकि एक सौदे की समय सीमा समाप्त;। रेफरी,, टिप्पणी here

आशा है कि यह

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