2009-11-30 7 views
6

मैं एक पृष्ठभूमि सेवा लिख ​​रहा हूं जिसे एक वर्ग की श्रृंखला को संसाधित करने की आवश्यकता है, जिसे SQL सर्वर तालिका में रिकॉर्ड के रूप में संग्रहीत किया जाता है। सेवा को सबसे पुरानी 20 नौकरियों को खोजने की ज़रूरत है जिन्हें काम करने की आवश्यकता है (where status = 'new'), उन्हें चिह्नित करें (set status = 'processing'), उन्हें चलाएं, और बाद में नौकरियों को अपडेट करें।परमाणु रूप से डेटाबेस में पंक्तियों के समूह को चिह्नित और वापस करें

यह पहला भाग है जिसके लिए मुझे सहायता चाहिए। एक ही समय में डेटाबेस तक पहुंचने वाले कई धागे हो सकते हैं, और मैं यह सुनिश्चित करना चाहता हूं कि "मार्क & वापसी" क्वेरी परमाणु रूप से चलती है, या लगभग।

यह सेवा डेटाबेस तक पहुंचने के अपेक्षाकृत कम समय व्यतीत करेगी, और अगर नौकरी दो बार चलती है तो यह दुनिया का अंत नहीं है, इसलिए मैं बढ़ी सादगी के लिए एक से अधिक बार चल रही नौकरियों की एक छोटी संभावना को स्वीकार करने में सक्षम हो सकता हूं कोड में

ऐसा करने का सबसे अच्छा तरीका क्या है? मैं अपनी डेटा परत के लिए linq-to-sql का उपयोग कर रहा हूं, लेकिन मुझे लगता है कि मुझे इसके लिए टी-एसक्यूएल में ड्रॉप करना होगा।

उत्तर

10

आपका तालिका नौकरियों की एक कतार है। उपयोगकर्ता टेबल बैक अप कतार लिखना एक कुख्यात त्रुटि प्रवण है क्योंकि यह डेडलॉक्स और अव्यवस्था के मुद्दों की ओर जाता है।

सबसे आसान बात उपयोगकर्ता तालिका को छोड़ना और इसके बजाय एक वास्तविक queue का उपयोग करना होगा। यह सिस्टम परीक्षण और मान्य कोड बेस पर आपको डेडलॉक मुफ्त concurency मुफ्त कतार देगा। समस्या यह है कि कतारों के आस-पास का प्रतिमान INSERT और DELETE/UPDATE से SEND/RECEIVE में बदल जाता है। दूसरी ओर अंतर्निर्मित कतार के साथ आपको कुछ बहुत शक्तिशाली मुफ्त उपहार मिलते हैं, अर्थात् Activation और correlated items locking

आप नीचे उपयोगकर्ता तालिका समर्थित कतारों के रास्ते तो उपयोगकर्ता टेबल कतारों लिखित रूप में दूसरा सबसे महत्वपूर्ण चाल जारी रखना चाहते हैं अद्यतन का उपयोग है ... उत्पादन:

WITH cte AS (
    SELECT TOP(20) status, id, ... 
    FROM table WITH (ROWLOCK, READPAST, UPDLOCK) 
    WHERE status = 'new' 
    ORDER BY enqueue_time) 
UPDATE cte 
    SET status = 'processing' 
OUTPUT 
    INSERTED.id, ... 

CTE वाक्य रचना है बस ऊपर और ऑर्डर सही तरीके से रखने की सुविधा के लिए, क्वेरी को व्युत्पन्न तालिकाओं का उपयोग करके लिखित रूप में लिखा जा सकता है। आप सीधे अद्यतन का उपयोग नहीं कर सकते ...शीर्ष क्योंकि अद्यतन एक ऑर्डर द्वारा समर्थित नहीं है और आपको इसकी आवश्यकता के 'सबसे पुराने' हिस्से को पूरा करने के लिए इसकी आवश्यकता है। समांतर प्रसंस्करण धागे के बीच उच्च सहमति की सुविधा के लिए लॉक संकेतों की आवश्यकता होती है।

मैंने कहा कि यह दूसरी सबसे महत्वपूर्ण चाल है। सबसे महत्वपूर्ण यह है कि आप तालिका को व्यवस्थित कैसे करते हैं। एक कतार के लिए यह (status, enqueue_time) द्वारा क्लस्टर किया जाना चाहिए। यदि आप तालिका को व्यवस्थित रूप से व्यवस्थित नहीं करते हैं तो आप डेडलॉक्स के साथ समाप्त हो जाएंगे। पूर्व-खाली टिप्पणी: इस परिदृश्य में विखंडन ire प्रासंगिक है।

+0

क्या आप समझा सकते हैं कि यदि आपके द्वारा निर्धारित 3 संकेतों का उपयोग करने के बाद भी तालिका को क्लस्टर नहीं किया गया है (स्थिति, enqueue_time)? –

+0

मुझे आउटपुट क्लॉज के बारे में पता नहीं था, जो संकेतों के साथ एक पूर्ण समाधान बनाता है। यह SO पर अपने स्वयं के प्रश्न का उत्तर देता है। –

8

कृपया मेरा उत्तर यहां देखें: SQL Server Process Queue Race Condition जो एक ही बार में 20 पंक्तियों का प्रबंधन करता है।

असल में, यह SQL सर्वर में ROWLOCK, READPAST और UPDLOCK संकेतों का उपयोग करके समेकन और मतदान का प्रबंधन करने के लिए काफी सरल है।

मैं Linq के बारे में टिप्पणी नहीं कर सकते, लेकिन लेन-देन अभी भी आप संगामिति मुद्दों के लिए खुला छोड़कर: यदि आप संकेत मैं

+0

आपके अन्य लेख बहुत उपयोगी थे। मैं तीन संकेतों में से एक गायब था। –

1

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

+0

क्व्यूइंग उत्तर है, लेकिन एमएसएमक्यू क्यों SQL सर्वर कतार में निर्मित के साथ आता है? –

+0

जिस तरह से मैं उनका उपयोग करता हूं वह प्रक्रियाओं को नियंत्रित करना है। जब मैं कुछ कतार करता हूं तो मैं डेटाबेस का उपयोग नहीं करता हूं। तो किसी भी सूचीकार को नौकरी मिल सकती है। और मैंने इसे 5 कंप्यूटरों के साथ 10 प्रक्रियाओं के साथ परीक्षण किया और मुझे कभी भी एक सहमति समस्या नहीं मिली। मुझे लगता है कि यह निर्भर करता है कि आप कहां रहना चाहते हैं। –

0

क्या यह आपके टी-एसक्यूएल को लेनदेन के भीतर चलाने जैसा आसान नहीं है, या क्या मुझे कुछ याद आ रही है?

4

gbn's answer पर भवन ...

आप उपयोग कर रहे हैं SQL सर्वर 2005 या नए, आप अपने UPDATE बयान में एक OUTPUT clause का उपयोग करके atomically अद्यतन पंक्तियों को वापस कर सकते हैं:

UPDATE TOP (20) your_table 
SET status = 'processing' 
OUTPUT INSERTED.* 
FROM your_table WITH (ROWLOCK, READPAST, UPDLOCK) 
WHERE status = 'new' 
संबंधित मुद्दे