5

alt textडेडलॉक! दो वास्तविक समय थोक अप्स लड़ रहे हैं। क्यूं कर?</p> <p>मैं एक मेज MarketDataCurrent (MDC) कहा जाता है कि लाइव स्टॉक की कीमतों को अद्यतन करने की है:

यहाँ परिदृश्य है।

मुझे 'लाइवफिड' नामक एक प्रक्रिया मिली है जो तार से स्ट्रीमिंग की कीमतें पढ़ती है, आवेषण कतार में आती है, और 'अस्थायी अपलोड पर अस्थायी अपलोड' का उपयोग करती है और फिर एमडीसी तालिका में डालें/अपडेट करें। (बल्क यूपीएसर्ट)

मुझे एक और प्रक्रिया मिली है जो तब इस डेटा को पढ़ती है, अन्य डेटा की गणना करती है, और उसके बाद समान बल्क यूपीएसर्ट संग्रहित प्रो का उपयोग करके परिणाम को उसी तालिका में वापस सहेजती है।

तीसरा, ऐसे कई उपयोगकर्ता हैं जो सी # गुई एमडीसी तालिका को मतदान करते हैं और इससे अपडेट पढ़ते हैं।

अब, जब डेटा तेजी से बदल रहा है, तो चीजें बहुत आसानी से चल रही हैं, लेकिन फिर, बाजार के घंटों के बाद, हमने हाल ही में डेटाबेस से बाहर आने वाले डेडलॉक अपवादों की बढ़ती संख्या को देखना शुरू कर दिया है, आजकल हम 10 देखते हैं -20 एक दिन। यहां ध्यान देने योग्य अपमानजनक बात यह है कि ये तब होते हैं जब मान नहीं बदल रहे होते हैं। ,

alt text

मैं चल रहा है किसी SQL Profiler ट्रेस मिल गया है गतिरोध को पकड़ने, और यहाँ है -

CREATE TABLE [dbo].[MarketDataCurrent](
[MDID] [int] NOT NULL, 
[LastUpdate] [datetime] NOT NULL, 
[Value] [float] NOT NULL, 
[Source] [varchar](20) NULL, 
CONSTRAINT [PK_MarketDataCurrent] PRIMARY KEY CLUSTERED 
(
[MDID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

:

टेबल डेफ:

यहाँ सभी प्रासंगिक जानकारी है सभी ग्राफ क्या दिखते हैं।

alt text

प्रक्रिया 258, निम्नलिखित 'BulkUpsert' संग्रहीत proc कहा जाता है, बार-बार, जबकि 73 अगले एक बुला रहा है:

ALTER proc [dbo].[MarketDataCurrent_BulkUpload] 
@updateTime datetime, 
@source varchar(10) 
as 

begin transaction 

update c with (rowlock) set LastUpdate = getdate(), Value = t.Value, Source = @source 
from MarketDataCurrent c INNER JOIN #MDTUP t ON c.MDID = t.mdid 
where c.lastUpdate < @updateTime 
and c.mdid not in (select mdid from MarketData where LiveFeedTicker is not null  and  PriceSource like 'LiveFeed.%') 
and c.value <> t.value 

insert into MarketDataCurrent 
with (rowlock) 
select MDID, getdate(), Value, @source from #MDTUP 
where mdid not in (select mdid from MarketDataCurrent with (nolock)) 
and mdid not in (select mdid from MarketData where LiveFeedTicker is not null  and PriceSource like 'LiveFeed.%') 

commit 

और अन्य एक:

ALTER PROCEDURE [dbo].[MarketDataCurrent_LiveFeedUpload] 
AS 
begin transaction 

-- Update existing mdid 
UPDATE c WITH (ROWLOCK) SET LastUpdate = t.LastUpdate, Value = t.Value, Source = t.Source 
FROM MarketDataCurrent c INNER JOIN #TEMPTABLE2 t ON c.MDID = t.mdid; 

-- Insert new MDID 
INSERT INTO MarketDataCurrent with (ROWLOCK) SELECT * FROM #TEMPTABLE2 
WHERE MDID NOT IN (SELECT MDID FROM MarketDataCurrent with (NOLOCK)) 

-- Clean up the temp table 
DELETE #TEMPTABLE2 

commit 

स्पष्टीकरण के लिए, उन Temp टेबल्स को उसी कनेक्शन पर सी # कोड द्वारा बनाया जा रहा है और सी # एसक्यूएलकल्क कॉपी क्लास का उपयोग करके पॉप्युलेट किया गया है।

मेरे लिए ऐसा लगता है कि यह तालिका के पीके पर डेडलॉकिंग है, इसलिए मैंने उस पीके को हटाने और इसके बजाय एक अनोखा प्रतिबंध पर स्विच करने की कोशिश की लेकिन इससे 10 गुना डेडलॉक्स की संख्या में वृद्धि हुई।

मैं पूरी तरह से खो गया हूं कि इस स्थिति के बारे में क्या करना है और किसी भी सुझाव के लिए खुला हूं।

सहायता !!


XDL के लिए अनुरोध के जवाब में, यहाँ यह है:

<deadlock-list> 
<deadlock victim="processc19978"> 
    <process-list> 
    <process id="processaf0b68" taskpriority="0" logused="0" waitresource="KEY: 6:72057594090487808 (d900ed5a6cc6)" waittime="718" ownerId="1102128174" transactionname="user_transaction" lasttranstarted="2010-06-11T16:30:44.750" XDES="0xffffffff817f9a40" lockMode="U" schedulerid="3" kpid="8228" status="suspended" spid="73" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-11T16:30:44.750" lastbatchcompleted="2010-06-11T16:30:44.750" clientapp=".Net SqlClient Data Provider" hostname="RISKAPPS_VM" hostpid="3836" loginname="RiskOpt" isolationlevel="read committed (2)" xactid="1102128174" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> 
    <executionStack> 
    <frame procname="MKP_RISKDB.dbo.MarketDataCurrent_BulkUpload" line="28" stmtstart="1062" stmtend="1720" sqlhandle="0x03000600a28e5e4ef4fd8e00849d00000100000000000000"> 
UPDATE c WITH (ROWLOCK) SET LastUpdate = getdate(), Value = t.Value, Source = @source 
FROM MarketDataCurrent c INNER JOIN #MDTUP t ON c.MDID = t.mdid 
WHERE c.lastUpdate &lt; @updateTime 
and c.mdid not in (select mdid from MarketData where BloombergTicker is not null and PriceSource like &apos;Blbg.%&apos;) 
and c.value &lt;&gt; t.value  </frame> 
    <frame procname="adhoc" line="1" stmtstart="88" sqlhandle="0x01000600c1653d0598706ca7000000000000000000000000"> 
exec MarketDataCurrent_BulkUpload @clearBefore, @source  </frame> 
    <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000"> 
unknown  </frame> 
    </executionStack> 
    <inputbuf> 
(@clearBefore datetime,@source nvarchar(10))exec MarketDataCurrent_BulkUpload @clearBefore, @source </inputbuf> 
    </process> 
    <process id="processc19978" taskpriority="0" logused="0" waitresource="KEY: 6:72057594090487808 (74008e31572b)" waittime="718" ownerId="1102128228" transactionname="user_transaction" lasttranstarted="2010-06-11T16:30:44.780" XDES="0x380be9d8" lockMode="U" schedulerid="5" kpid="8464" status="suspended" spid="248" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-11T16:30:44.780" lastbatchcompleted="2010-06-11T16:30:44.780" clientapp=".Net SqlClient Data Provider" hostname="RISKBBG_VM" hostpid="4480" loginname="RiskOpt" isolationlevel="read committed (2)" xactid="1102128228" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> 
    <executionStack> 
    <frame procname="MKP_RISKDB.dbo.MarketDataCurrentBlbgRtUpload" line="14" stmtstart="840" stmtend="1220" sqlhandle="0x03000600005f9d24c8878f00849d00000100000000000000"> 
UPDATE c WITH (ROWLOCK) SET LastUpdate = t.LastUpdate, Value = t.Value, Source = t.Source 
     FROM MarketDataCurrent c INNER JOIN #TEMPTABLE2 t ON c.MDID = t.mdid; 

     -- Insert new MDID  </frame> 
    <frame procname="adhoc" line="1" sqlhandle="0x010006004a58132228bf8d73000000000000000000000000"> 
MarketDataCurrentBlbgRtUpload  </frame> 
    </executionStack> 
    <inputbuf> 
MarketDataCurrentBlbgRtUpload </inputbuf> 
    </process> 
    </process-list> 
    <resource-list> 
    <keylock hobtid="72057594090487808" dbid="6" objectname="MKP_RISKDB.dbo.MarketDataCurrent" indexname="PK_MarketDataCurrent" id="lock5ba77b00" mode="U" associatedObjectId="72057594090487808"> 
    <owner-list> 
    <owner id="processc19978" mode="U"/> 
    </owner-list> 
    <waiter-list> 
    <waiter id="processaf0b68" mode="U" requestType="wait"/> 
    </waiter-list> 
    </keylock> 
    <keylock hobtid="72057594090487808" dbid="6" objectname="MKP_RISKDB.dbo.MarketDataCurrent" indexname="PK_MarketDataCurrent" id="lock65dca340" mode="U" associatedObjectId="72057594090487808"> 
    <owner-list> 
    <owner id="processaf0b68" mode="U"/> 
    </owner-list> 
    <waiter-list> 
    <waiter id="processc19978" mode="U" requestType="wait"/> 
    </waiter-list> 
    </keylock> 
    </resource-list> 
</deadlock> 
</deadlock-list> 
+0

क्या होगा यदि आप स्पष्ट चप्पू-आंकड़ा और nolock विनिर्देशक निकालना चाहते हैं? क्या टेबल के बजाए आपके प्रश्नों के विचारों में उल्लिखित डेटा स्रोत हैं, और यदि ऐसा है तो कृपया दृश्य स्रोत पोस्ट करें? धन्यवाद। –

+0

डेटा स्रोतों में से कोई भी विचार नहीं है। असल में, स्पष्टीकरण रोलॉक और नोलॉक्स जोड़ने से डेडलॉक्स की संख्या कम हो गई। – skimania

+1

वास्तविक डेडलॉक एक्सडीएल बेहतर पोस्ट करें, छवि नहीं। छवियां धोखा दे सकती हैं ... http://rusanu.com/2010/05/12/the-puzzle-of-u-locks-in-deadlock-graphs/ –

उत्तर

0

मैंने आखिरकार इस समस्या को हल किया है, लगभग दो साल के कष्टप्रद डेडलॉक चेतावनी ईमेल के बाद।

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

इसके अतिरिक्त, MERGE का उपयोग करके एक परमाणु कथन में सम्मिलित/अद्यतन को संयोजित करने से मुझे ऐसा करने की अनुमति मिलती है।

यहाँ का समाधान उत्पादन कोड है (यह काम करता है!):

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

merge marketdatacurrent with (tablockx) as mdc 

using #MDTUP as upload 
    on mdc.MDID = upload.MDID 

when matched then 
    update 
    set mdc.lastupdate = @date, 
     mdc.value = upload.value, 
     mdc.source = @source 

when not matched then 
    insert (mdid, lastupdate, value, source) 
    values (upload.mdid, @date, upload.value, @source); 
+0

!!! TABLOCKX TABLOCKX TABLOCKX TABLOCKX TABLOCKX TABLOCKX !!! – skimania

+0

WOOOOOOOOOOOOOOOOOOOOOOOOO !!!! – skimania

1

यह मुख्य व्यवसाय घंटे के बाद हो रहा है, डेटा नहीं बदल रहा है और यह अभी हाल ही में शुरू कर दिया। क्या हाल ही में सर्वर पर कुछ भी बदल गया है?मुझे संदेह होगा कि कुछ नए डेटाबेस रखरखाव नौकरी में हस्तक्षेप हो सकता है।

बीटीडब्ल्यू अगर आपको पता है कि बाजार बंद है और डेटा नहीं बदल रहा है, तो आपकी प्रक्रिया अभी भी क्यों चल रही है?

+0

मैं सर्वर का प्रबंधन करता हूं और उस पर चलने वाली सभी चीज़ों को जानता हूं। एक एसक्यूएल डीटीएसएस बैकअप जॉब है जो हर रात एक ही भौतिक हार्ड ड्राइव पर पूर्ण बैकअप करता है, फिर एक और एसक्यूएल सर्वर पर एक और डीटीएसएस जो मेरे सर्वर के स्थानीय ड्राइव से नेटवर्क 'स्नैप सर्वर' पर प्रतिलिपि बनाता है – skimania

+0

मैं डेटा के बारे में अधिक जानकारी देता हूं बिल्कुल अद्यतन नहीं कर रहा है। ज्यादातर बाजार बंद हैं, लेकिन एफएक्स वास्तव में 24/5 खुला है इसलिए हमें उस बाजार को संसाधित करने की आवश्यकता है। – skimania

2

डेडलॉक मुख्य पहुंच आदेश पर सीधे आगे के डेडलॉक्स प्रतीत होता है। एक छोटी व्याख्या दो थोक अद्यतन संचालन के बीच अद्यतन कुंजी का ओवरलैप है।

हालांकि एक कम मामूली स्पष्टीकरण है कि SQL सर्वर (और अन्य सर्वर भी) में लॉक की गई कुंजियां हैं है, और एक (बहुत महत्वपूर्ण) हैश टक्कर संभावना है। यह समझाएगा कि आप हाल ही में तुलना में अधिक डेडलॉक्स क्यों देखते हैं: बस डेटा की मात्रा में वृद्धि हुई है और इसलिए टकराव की संभावना बढ़ गई है। यदि यह गूढ़ और असंभव लगता है, तो बस %%lockres%% collision probability magic marker: 16,777,215 पर पढ़ें, और उस से जुड़ा लेख। सही कुंजी वितरण के लिए संभावना ~ आश्चर्यजनक रूप से उच्च है, केवल ~ 16 एम आवेषण के बाद आपके पास 50% टक्कर संभावना है। सामान्य, वास्तविक दुनिया के लिए, महत्वपूर्ण वितरण आपके पास केवल कुछ हज़ार आवेषणों पर महत्वपूर्ण टकराव की संभावना है। दुर्भाग्य से, कोई काम नहीं है। आपका एकमात्र समाधान, यदि यह वास्तव में समस्या है, तो बैचों के आकार को कम करना है (#temp टेबल का आकार) ताकि टकराव की संभावना कम हो। या डेडलॉक्स से निपटें और पुनः प्रयास करें ... जो आपको वैसे भी करना होगा, लेकिन कम से कम आप कम डेडलॉक्स से निपट सकते हैं।

+0

इस अंतर्दृष्टि अब तक बहुत उपयोगी रही है। मैं तब तक कोई जवाब स्वीकार नहीं कर सकता जब तक कि मैं इन डेडलॉक्स को स्वीकार्य स्तर तक कम करने के तरीके से नहीं आ जाता, लेकिन मुझे लगता है कि यह सही रास्ते पर है। आपका आलेख इस से लिंक करता है, जो बहुत ही रोचक है: http://consultingblogs.emc.com/jamesrowlandjones/archive/2009/05/28/the-curious-case-of-the-dubious-deadlock-and -इस-नहीं-तो-तार्किक-lock.aspx वह इस मुद्दे के तीन संभावित हल, जिनमें से # 1 1. बदलें एक किराए पूर्णांक की कुंजी आधारित महत्वपूर्ण है उल्लेख है लेकिन यह ठीक है कि मैं क्या है । इस तालिका में पीके एक अनोखा int है, और कुछ भी नहीं – skimania

+0

मैं वास्तव में उस पर जेम्स से असहमत हूं। एक int सरोगेट कुंजी के लिए कुंजी बदलना बिल्कुल कुछ नहीं करेगा, 8 बाइट int अभी भी लॉक संसाधन आकार में डाला जाएगा, जो कि 6 बाइट्स है। IMHO। बैच आकार को कम करने का एकमात्र उचित तरीका है। –

+0

बस भाग गया: %% lockres %% होने गिनती (*)> 1 द्वारा %% lockres चयन %% LockHas के रूप में, MarketDataCurrent समूह से गिनती (*) (दिन के मध्य में) और 0 पंक्तियां मिली! हमारी तालिका वास्तव में वह सब बड़ी नहीं है। ~ 32,000 पंक्तियां कुल (यह बहुत हल्का होना चाहिए और केवल वास्तविक समय डेटा होना चाहिए) तो, एक अद्वितीय int id pk के साथ, और 250,000 तक की सीमा में मान हैश कुंजी टकराव एक स्पष्टीकरण के रूप में लगभग असंभव प्रतीत होता है। मैं इस प्रश्न को फिर से अगले डेडलॉक के बाद फिर से देखूंगा कि यह देखने के लिए कि क्या कोई बिंदु है, लेकिन मुझे उनकी उम्मीद नहीं है। – skimania

1

मैं एक सवाल मैं एक टिप्पणी है, जिसमें पूछा,

"कैसे आप पंक्तियों जो ताला लगा रहे हैं की पहचान करते हैं?" जवाब देने के लिए करना चाहते हैं।

निम्नलिखित डेडलॉक एक्सडीएल में, लॉकिंग वाले दो "प्रक्रिया" नोड्स पर, waitresource विशेषता है। इस मामले में:

waitresource="KEY: 6:72057594090487808 (d4005c04b35f)

और

waitresource="KEY: 6:72057594090487808 (b00072ea4ffd)

%%lockres%% कीवर्ड Remus की ओर इशारा का उपयोग करना,

select %%lockres%%, * from MarketDataCurrent 
    where %%lockres%% in ('(d4005c04b35f)', '(b00072ea4ffd)') 

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

मुझे पता चलेगा कि दोनों आईडी केवल लाइवफिड प्रोग्राम से आ रही हैं, लेकिन फिर, अद्यतन में एक खंड है जो वास्तव में दूसरी तरफ से अपडेट करने से इस पंक्ति को फ़िल्टर करना है।

<deadlock-list> 
<deadlock victim="processffffffff8f5872e8"> 
    <process-list> 
    <process id="process8dcb68" taskpriority="0" logused="1256" waitresource="KEY: 6:72057594090487808 (d4005c04b35f)" waittime="1906" ownerId="1349627324" transactionname="user_transaction" lasttranstarted="2010-06-16T16:50:04.727" XDES="0x424e6258" lockMode="U" schedulerid="2" kpid="1004" status="suspended" spid="683" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-16T16:50:04.727" lastbatchcompleted="2010-06-16T16:50:04.727" clientapp=".Net SqlClient Data Provider" hostname="RISKAPPS_VM" hostpid="2600" loginname="RiskOpt" isolationlevel="read committed (2)" xactid="1349627324" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> 
    <executionStack> 
    <frame procname="MKP_RISKDB.dbo.MarketDataCurrent_BulkUpload" line="28" stmtstart="1062" stmtend="1720" sqlhandle="0x03000600a28e5e4ef4fd8e00849d00000100000000000000"> 
     UPDATE c WITH (ROWLOCK) SET LastUpdate = getdate(), Value = t.Value, Source = @source 
     FROM MarketDataCurrent c INNER JOIN #MDTUP t ON c.MDID = t.mdid 
     WHERE c.lastUpdate &lt; @updateTime 
     and c.mdid not in (select mdid from MarketData where BloombergTicker is not null and PriceSource like &apos;Blbg.%&apos;) 
     and c.value &lt;&gt; t.value  </frame> 
      <frame procname="adhoc" line="1" stmtstart="88" sqlhandle="0x01000600c1653d0598706ca7000000000000000000000000"> 
     exec MarketDataCurrent_BulkUpload @clearBefore, @source  </frame> 
    <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">unknown</frame> 
    </executionStack> 
    <inputbuf>(@clearBefore datetime,@source nvarchar(10))exec MarketDataCurrent_BulkUpload @clearBefore, @source</inputbuf> 
    </process> 
    <process id="processffffffff8f5872e8" taskpriority="0" logused="0" waitresource="KEY: 6:72057594090487808 (b00072ea4ffd)" waittime="1921" ownerId="1349627388" transactionname="user_transaction" lasttranstarted="2010-06-16T16:50:04.757" XDES="0x289ea040" lockMode="U" schedulerid="5" kpid="11192" status="suspended" spid="382" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-16T16:50:04.757" lastbatchcompleted="2010-06-16T16:50:04.757" clientapp=".Net SqlClient Data Provider" hostname="RISKBBG_VM" hostpid="2452" loginname="RiskOpt" isolationlevel="read committed (2)" xactid="1349627388" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> 
    <executionStack> 
    <frame procname="MKP_RISKDB.dbo.MarketDataCurrentBlbgRtUpload" line="14" stmtstart="840" stmtend="1220" sqlhandle="0x03000600005f9d24c8878f00849d00000100000000000000"> 
     UPDATE c WITH (ROWLOCK) SET LastUpdate = t.LastUpdate, Value = t.Value, Source = t.Source 
     FROM MarketDataCurrent c INNER JOIN #TEMPTABLE2 t ON c.MDID = t.mdid; 
    </frame> 
    <frame procname="adhoc" line="1" sqlhandle="0x010006004a58132228bf8d73000000000000000000000000"> 
     MarketDataCurrentBlbgRtUpload  </frame> 
    </executionStack> 
    <inputbuf> 
     MarketDataCurrentBlbgRtUpload </inputbuf> 
    </process> 
    </process-list> 
    <resource-list> 
    <keylock hobtid="72057594090487808" dbid="6" objectname="MKP_RISKDB.dbo.MarketDataCurrent" indexname="PK_MarketDataCurrent" id="lock409d32c0" mode="U" associatedObjectId="72057594090487808"> 
    <owner-list> 
    <owner id="processffffffff8f5872e8" mode="U"/> 
    </owner-list> 
    <waiter-list> 
    <waiter id="process8dcb68" mode="U" requestType="wait"/> 
    </waiter-list> 
    </keylock> 
    <keylock hobtid="72057594090487808" dbid="6" objectname="MKP_RISKDB.dbo.MarketDataCurrent" indexname="PK_MarketDataCurrent" id="lock706647c0" mode="U" associatedObjectId="72057594090487808"> 
    <owner-list> 
    <owner id="process8dcb68" mode="U"/> 
    </owner-list> 
    <waiter-list> 
    <waiter id="processffffffff8f5872e8" mode="U" requestType="wait"/> 
    </waiter-list> 
    </keylock> 
    </resource-list> 
</deadlock> 
</deadlock-list>