कुशल लेनदेन, रिकॉर्ड लॉकिंग


5

मुझे एक संग्रहित प्रक्रिया मिली है, जो 1 रिकॉर्ड बैक का चयन करती है। संग्रहित प्रक्रिया को विभिन्न पीसी पर कई अलग-अलग अनुप्रयोगों से बुलाया जा सकता है। विचार यह है कि संग्रहीत प्रक्रिया अगले रिकॉर्ड को वापस लाती है जिसे संसाधित करने की आवश्यकता होती है, और यदि दो अनुप्रयोग एक ही समय में संग्रहित प्रो को कॉल करते हैं, तो उसी रिकॉर्ड को वापस नहीं लाया जाना चाहिए। मेरी क्वेरी नीचे है, मैं क्वेरी को यथासंभव कुशलतापूर्वक लिखने की कोशिश कर रहा हूं (एसक्यूएल 2008)। क्या इससे इससे अधिक कुशलता से किया जा सकता है?

CREATE PROCEDURE GetNextUnprocessedRecord 
AS 
BEGIN 
    SET NOCOUNT ON; 

    --ID of record we want to select back 
    DECLARE @iID BIGINT  

    -- Find the next processable record, and mark it as dispatched 
    -- Must be done in a transaction to ensure no other query can get 
    -- this record between the read and update 
    BEGIN TRAN 

     SELECT TOP 1 
      @iID = [ID] 
     FROM 
      --Don't read locked records, only lock the specific record 
      [MyRecords] WITH (READPAST, ROWLOCK) 
     WHERE 
      [Dispatched] is null 
     ORDER BY 
      [Received] 

     --Mark record as picked up for processing 
     UPDATE 
      [MyRecords] 
     SET 
      [Dispatched] = GETDATE() 
     WHERE 
      [ID] = @iID  

    COMMIT TRAN 

    --Select back the specific record 
    SELECT 
     [ID], 
     [Data] 
    FROM  
     [MyRecords] WITH (NOLOCK, READPAST) 
    WHERE 
     [ID] = @iID 

END 
  0

में करता है मैं इस TSQL आश्वस्त नहीं कर रहा हूँ इस्तेमाल कर सकते हैं transactionally है सुरक्षित ... 22 feb. 092009-02-22 08:07:45

  0

चयन के बाद और अद्यतन से पहले WAITFOR DELAY '0: 2: 0' डालने का प्रयास करें, एसपी चलाएं और उसी एसपी को किसी अन्य कनेक्शन से निष्पादित करें ... 22 feb. 092009-02-22 08:17:24

  0

असल में, मैं गलत हूं! होल्डॉक के समान प्रभाव है जैसा कि MyRecords तालिका पर REPEATABLEREAD है। 22 feb. 092009-02-22 08:22:27

  0

यह डिफ़ॉल्ट रूप से बेहतर सुरक्षित है। अन्यथा ढीले पर व्यापक वैचारिक अराजकता है। 22 feb. 092009-02-22 08:43:46

  0

मुझे अभी भी लगता है कि आपको REPEATABLEREAD 22 feb. 092009-02-22 08:55:17

3

रीडपैस्ट लॉकिंग संकेत का उपयोग करना सही है और आपका एसक्यूएल ठीक दिखता है।

मैं उपयोग XLOCK जोड़ना होगा जो हालांकि यह भी HOLDLOCK/serializable है

... 
[MyRecords] WITH (READPAST, ROWLOCK, XLOCK) 
... 

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

संपादित करें: इसे त्वरित बनाने के लिए प्रेषित और प्राप्त कॉलम पर एक अनुक्रमणिका जोड़ें। यदि [आईडी] (मुझे लगता है कि यह पीके है) क्लस्टर्ड नहीं है, [आईडी] शामिल करें। क्योंकि यह एसक्यूएल 2008

है और भी सूचकांक को फ़िल्टर इस निर्माण जो यह सब XLOCK बिना एक ही बार या HOLDLOCK

UPDATE 
    MyRecords 
SET 
    --record the row ID 
    @id = [ID], 
    --flag doing stuff 
    [Dispatched] = GETDATE() 
WHERE 
    [ID] = (SELECT TOP 1 [ID] FROM MyRecords WITH (ROWLOCK, READPAST) WHERE Dispatched IS NULL ORDER BY Received) 

UPDATE, assign, set in one

  0

अद्भुत टिप्स! मैंने एक्सलॉक संकेत जोड़ा है और प्राप्त और प्रेषित पर एक गैर क्लस्टर इंडेक्स बनाया है, और "प्रेषित आईएस नल" के फ़िल्टर के साथ आईडी शामिल है। यह आईडी पर मेरे क्लस्टर इंडेक्स के अतिरिक्त है। मैं अभी भी यह पता लगाने की कोशिश कर रहा हूं कि एक में अद्यतन असाइनमेंट सेट तेज है या नहीं। 23 feb. 092009-02-23 07:07:14

+1

धन्यवाद। मैं सीधे प्रदर्शन से लेनदेन संबंधी अखंडता के बारे में और चिंता करता हूं। एकल कथन XLOCK की आवश्यकता को हटा देता है। 23 feb. 092009-02-23 07:48:33


0

आप प्रत्येक पिकर प्रक्रिया को एक अद्वितीय आईडी असाइन कर सकते हैं, और कॉलम पिकरप्रोक और अपने रिकॉर्ड में पिकस्टेट जोड़ सकते हैं। तब

अद्यतन MyRecords
सेट pickerproc = myproc,
pickstate = 'मैं' - के लिए 'I'n प्रक्रिया
कहां आईडी = (चयन मैक्स (आईडी) MyRecords से कहां pickstate =' ए ') - 'उपलब्ध'

यह आपको एक परमाणु चरण में अपना रिकॉर्ड प्राप्त करता है, और आप अपने अवकाश पर अपने बाकी संसाधनों को कर सकते हैं। फिर आप पिकस्टेट को 'C'omplete', 'E'rror, या जो कुछ भी हल हो जाते हैं, पर सेट कर सकते हैं।

मुझे लगता है कि मिच एक और अच्छी तकनीक का जिक्र कर रहा है जहां आप एक संदेश-कतार तालिका बनाते हैं और वहां आईडी डालते हैं। कई SO धागे हैं - 'संदेश कतार तालिका' के लिए खोजें।

  0

की तुलना में लेनदेन को सर्जिकल बनाने की आवश्यकता होगी जो निश्चित रूप से सुरक्षित नहीं है! 22 feb. 092009-02-22 08:51:33

  0

और वह क्यों होगा? यह पिकस्टेट 'ए' के ​​साथ उसी MAX (आईडी) को बंद करने वाला नहीं है जब तक कि आप इसे बदल नहीं लेते। कम से कम यह मेरे अनुभव में शायद 10^6 + उदाहरणों के आधार पर नहीं है। 22 feb. 092009-02-22 08:55:38

  0

.. और यह कुशल नहीं होगा 22 feb. 092009-02-22 08:57:49

  0

मैं सुन रहा हूं ... आपका तर्क क्या है? मैं हमेशा एसक्यूएल के बारे में और जान सकता हूं ... 22 feb. 092009-02-22 09:00:29

  0

@le dorfier: उस लेनदेन को लगातार बनाने के लिए, इसे एक सामान्य लेनदेन में लपेटने की आवश्यकता होगी। अन्यथा, गंदे पढ़ने/गैर-दोहराने योग्य पढ़ने/प्रेत पढ़ने/ 22 feb. 092009-02-22 09:01:27

  0

का जोखिम होने तक जोखिम होने तक, MAX ऑपरेशन पंक्तियों को स्कैन करने जा रहा है। यदि यह एक बड़ी मेज है, तो यह अपेक्षाकृत लंबे समय तक एक खुराक खुलेगा। 22 feb. 092009-02-22 09:03:12

  0

मुझे उस टर्गिड लॉक दस्तावेज़ को फिर से समझने से नफरत है, लेकिन मैं इस धारणा के लिए शुरू करता हूं कि एसीआईडी ​​डिफ़ॉल्ट रूप से लागू होता है। आप असहमत हैं? 22 feb. 092009-02-22 09:03:40

  0

(प्रतिबिंब पर) मैं आपका बिंदु देखता हूं (यानी पिकस्टेट कॉलम की निम्न कार्डिनालिटी)। लेकिन यह SQL 2008 में उपलब्ध "फ़िल्टर किए गए इंडेक्स" द्वारा हल किया गया है। Http://blog.sqlauthority.com/2008/09/01/sql-server-2008-introduction-to-filtered-index-improve-performance-with देखें -फिल्टर-इंडेक्स/ 22 feb. 092009-02-22 09:18:22


0

आप तेजी से प्रसंस्करण के लिए MyRecords को "स्मृति" तालिका पर रख सकते हैं।

  0

तालिका काफी बड़ी हो सकती है, साथ ही, सर्वर क्रैश होने पर क्या होता है? 22 feb. 092009-02-22 19:27:06