समवर्ती तालिका आधारित कतार को लागू करने का सबसे अच्छा तरीका


11

मेरे पास MySQL में एक तालिका है जो संसाधित होने वाली लिंक की एक कतार का प्रतिनिधित्व करती है। लिंक एक बाहरी ऐप द्वारा संसाधित किए जाते हैं, एक-एक करके और अंत में हटाए जाते हैं। यह एक उच्च मात्रा कतार है और मेरे पास कई सर्वरों में फैले प्रसंस्करण ऐप के कई उदाहरण हैं।

मैं यह कैसे सुनिश्चित कर सकता हूं कि प्रत्येक रिकॉर्ड केवल एक ऐप द्वारा चुना जाए? क्या रिकॉर्ड को ध्वजांकित / लॉक करने का कोई तरीका है?

अभी, एक ही लिंक को दो या दो से अधिक लेने से बचने के लिए, मैं प्रत्येक उदाहरण को केवल एक निश्चित रिकॉर्ड (अपनी आईडी के मॉड में आधारित) लेने की अनुमति दे रहा हूं, लेकिन यह कतार प्रसंस्करण को बढ़ाने का पारदर्शी तरीका नहीं है बस नए उदाहरण जोड़कर गति।


मेरा मंत्र: "इसे कतार में मत लगाओ, बस करो"। यानी किसी कार्य को कतार में फेंकने के बजाय, कार्य करने के लिए एक प्रक्रिया शुरू करें।
रिक जेम्स

जवाबों:


8

पहला: इसे लागू करने के लिए MySQL सॉफ्टवेयर के सबसे खराब संभावित टुकड़ों में से एक है, खासकर अगर यह बहुत गतिशील है। इसका कारण यह है कि MEMORY और MyISAM जैसे इंजनों में केवल फुल-टेबल लॉक होते हैं, जबकि अधिक उपयुक्त इंजन जैसे InnoDB में उच्च लिखने का दंड (ACID गुण प्रदान करने के लिए) होता है और वे उन रिकॉर्ड तक पहुँचने के लिए अनुकूलित होते हैं, जो स्थानिक और अस्थायी रूप से पास होते हैं (जो मेमोरी पर सेट होते हैं )। MySQL के लिए एक अच्छा बदलाव अधिसूचना प्रणाली भी नहीं है- इसे मतदान के रूप में लागू किया जाना है। कर रहे हैं और अधिक है कि काम के लिए अनुकूलित सॉफ्टवेयर के टुकड़े के दर्जनों

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

SELECT FOR UPDATEवह है जो आप देख रहे हैं- क्रमांकन पढ़ें। हालांकि एक UPDATE / DELETE हमेशा रनिंग MYSQL लेनदेन के दौरान पंक्ति को लॉक करेगा, आप प्रक्रिया को चालू करते समय एक बड़े लेनदेन से बचना चाह सकते हैं, इसलिए:

START TRANSACTION;
SELECT * FROM your_table WHERE state != 'PROCESSING' 
  ORDER BY date_added ASC LIMIT 1 FOR UPDATE;
if (rows_selected = 0) { //finished processing the queue, abort}
else {
UPDATE your_table WHERE id = $row.id SET state = 'PROCESSING'
COMMIT;

// row is processed here, outside of the transaction, and it can take as much time as we want

// once we finish:
DELETE FROM your_table WHERE id = $row.id and state = 'PROCESSING' LIMIT 1;
}

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


धन्यवाद। क्या आपको लगता है कि प्रदर्शन एक बड़े लॉक (10 को कहने के लिए लिमिट को बदलकर) से लाभ उठा सकता है?
मिगेल ई

@ मिगुएल सामान्य तौर पर, हाँ, जितना अधिक समय आप प्रसंस्करण में बिताते हैं और कम संभावना है कि आप अन्य लेनदेन से टकराते हैं, उतना ही बेहतर होगा। लेकिन यह कुछ मामलों में निर्भर हो सकता है- यह विपरीत प्रभाव (अधिक लेन-देन लॉक होने) का कारण भी हो सकता है। हमेशा इसे पहले परखें। तालिका को पर्याप्त रूप से अनुक्रमित करना भी महत्वपूर्ण है, या आप कुछ अलगाव मोड में पूर्ण तालिका लॉक के साथ समाप्त हो सकते हैं।
19

1
और शायद यह एक अच्छा विचार होगा कि जिस तारीख को आप लटकाते हैं, उस तिथि को ट्रैक करना शुरू कर दें और आप टाइमआउट तंत्र को लागू करना चाहते हैं।
जूलियन

3

जैसा कि मैंने इस लेख में बताया , MySQL 8 ने SKIP LOCKED और NO WAIT दोनों के लिए समर्थन पेश किया।

SKIP लॉक्ड काम की कतारों (उर्फ बैच कतारों) को लागू करने के लिए उपयोगी है, ताकि आप उन ताले को छोड़ सकें जो पहले से ही अन्य समवर्ती लेनदेन द्वारा बंद हैं।

जब तक समवर्ती लेन-देन लॉक जारी नहीं करता है तब तक प्रतीक्षा से बचने के लिए NO WAIT उपयोगी है। NO WAIT के बिना, हमें या तो तब तक इंतजार करना होगा जब तक कि ताले जारी न हो जाएं (वर्तमान में लेन-देन द्वारा लॉक या जारी करने का समय) या लॉक अधिग्रहण का समय समाप्त हो जाए। इसलिए, NO WAIT मान के साथ लॉक टाइमआउट की तरह काम करता है 0

SKIP LOCK और NO WAIT के बारे में अधिक जानकारी के लिए, इस लेख को देखें


0

मैंने ऑफलाइन डीबीसीसी चेक (बैकअप रिस्टोर करने वाले दो सर्वर और फिर डीबीसीसी चेकडब) के साथ भी कुछ ऐसा ही किया है। एक सर्वर कल सभी 31 सर्वर के बैकअप को इकट्ठा करता है और उन्हें एक कतार में रखता है और फिर उस सर्वर को और दूसरा उस कतार से खींचता है। हालांकि बहुत सारे सर्वर नहीं हैं, यह विधि समान ही होनी चाहिए: क्या एप्लिकेशन सर्वर ने दिनांक / समय क्षेत्र और उस ऐप सर्वर के नाम के साथ एक "ऐप सर्वर" फ़ील्ड को अपडेट करने वाली कतार के खिलाफ एक अपडेट क्वेरी चलाया है या अभी तक संख्यात्मक आईडी बेहतर है। यह एक लॉक का कारण होगा या अगर अगली पंक्ति को प्राप्त करने वाले किसी अन्य सर्वर से पहले से ही कोई लॉक है, तो इसे ब्लॉक किया जाएगा और अगली पंक्ति प्राप्त करने के लिए अन्य एप्लिकेशन के लिए प्रतीक्षा करें। फिर आप चाहते हैं कि एप्लिकेशन कतार से सबसे हाल के रिकॉर्ड को वापस खींच ले, क्योंकि यह ऐप फ़ील्ड है और इससे आपको जो भी जानकारी चाहिए। MySQL का उपयोग करना '

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.