2012-08-28 3 views
5

डेडलॉक्स से बचने और एकाधिक सेवाओं के अनुरोधों को सिंक्रनाइज़ करने का प्रयास करने में, मैं ROWLOCK, READPAST का उपयोग कर रहा हूं। मेरा सवाल यह है कि मुझे इसे एक प्रश्न में कहां रखना चाहिए जिसमें सीटीई, एक सबक्वायरी और सीटीई पर अपडेट स्टेटमेंट शामिल है? क्या कोई महत्वपूर्ण स्थान है या क्या तीनों स्थानों पर यह होना चाहिए (नीचे)? या हो सकता है कि ऐसी क्वेरी लिखने का एक बेहतर तरीका है ताकि मैं केवल उन पंक्तियों का चयन कर सकूं जिन्हें अपडेट किया जाएगा।ROWLOCK का उपयोग कहां करें, सीटीई, सबक्वायरी और अपडेट के साथ रीडपैस्ट?

alter proc dbo.Notification_DequeueJob 
    @jobs int = null 
as 

    set nocount on; 
    set xact_abort on; 

    declare @now datetime 
    set @now = getdate(); 

    if(@jobs is null or @jobs <= 0) set @jobs = 1 

    ;with q as (
     select 
      *, 
      dense_rank() over (order by MinDate, Destination) as dr 
     from 
     (
      select *, 
       min(CreatedDt) over (partition by Destination) as MinDate 
      from dbo.NotificationJob with (rowlock, readpast) 
     ) nj 

    where (nj.QueuedDt is null or (DATEDIFF(MINUTE, nj.QueuedDt, @now) > 5 and nj.CompletedDt is null)) 
    and (nj.RetryDt is null or nj.RetryDt < @now) 
    and not exists(
     select * from dbo.NotificationJob 
     where Destination = nj.Destination 
     and nj.QueuedDt is not null and DATEDIFF(MINUTE, nj.QueuedDt, @now) < 6 and nj.CompletedDt is null) 
    ) 
    update t 
     set t.QueuedDt = @now, 
      t.RetryDt = null 
    output 
     inserted.NotificationJobId, 
     inserted.Categories, 
     inserted.Source, 
     inserted.Destination, 
     inserted.Subject, 
     inserted.Message 
    from q as t 
    where t.dr <= @jobs 
go 

उत्तर

1

मेरे पास जवाब नहीं है, लेकिन ऐसे तरीके हैं जिनसे आप और जान सकते हैं।

आपके द्वारा लिखे गए कोड उचित लगता है। Proc के लिए वास्तविक क्वेरी योजना की जांच करने से यह सत्यापित करने में सहायता मिल सकती है कि SQL सर्वर उचित क्वेरी योजना भी उत्पन्न कर सकता है।

यदि आपके पास NotificationJob पर कोई अनुक्रमणिका नहीं है। डिस्टिनेशन जिसमें QueuedDt और CompletedDt शामिल है, not exists उप-क्वेरी पूरी तालिका पर साझा लॉक प्राप्त कर सकती है। यह समवर्ती के लिए डरावना होगा।

आप देख सकते हैं कि जब यह ताले प्राप्त करता है तो प्रो व्यवहार कैसे करता है। एक तरीका है trace flag 1200 अस्थायी रूप से चालू करना, अपनी proc को कॉल करें, और फिर ध्वज बंद करें। इससे बहुत अधिक उत्पन्न होगा जो कि प्रोसेस प्राप्त करने वाले लॉक के बारे में जानकारी के बारे में जानकारी देगा। जानकारी की मात्रा प्रदर्शन को गंभीर रूप से प्रभावित करेगी, इसलिए उत्पादन ध्वज में इस ध्वज का उपयोग न करें।

dbcc traceon (1200, -1) -- print detailed information for every lock request. DO NOT DO THIS ON A PRODUCTION SYSTEM! 
exec dbo.Notification_DequeueJob 
dbcc traceoff (1200, -1) -- turn off the trace flag ASAP 
संबंधित मुद्दे