2012-06-19 11 views
8

के रूप में चुना गया है मैंने एक निगरानी अनुप्रयोग विकसित किया है। इसलिए मैंने SQL तालिका में कुछ मानों की जांच करने के लिए टाइमर फ़ंक्शन का उपयोग किया है।लेनदेन (प्रक्रिया आईडी 84) लॉक संसाधनों पर एक और प्रक्रिया के साथ deadlocked था और डेडलॉक पीड़ित

हालांकि वहाँ इतने सारे समारोह कर रहे हैं यह getLogEntry कहा जाता है एक समारोह के लिए एक निम्न त्रुटि()

message>Transaction (Process ID 84) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.</message> 
<innerMessage> 
</innerMessage> 
<source>.Net SqlClient Data Provider</source> 
<stackTrace>at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlDataReader.HasMoreRows() 
    at System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) 
    at ShiftAlertSystem.DBAccess.getLogEntry(Int32 nEventLogIdn, connections cn)</stackTrace> 
    <createdAt>2012/06/18 13:10:47</createdAt> 

इस समारोह के कार्यान्वयन है

public LogEntry getLogEntry(int nEventLogIdn, connections cn) 
    { 
     lock (_objLock) 
     { 
      LogEntry lgEntObj = new LogEntry(); 
      SqlConnection NewCon3 = new SqlConnection(); 
      SqlCommand newCmd2 = null; 
      SqlDataReader dr = null; 

      try 
      { 


       string connectString; 
       // Configuration config = ConfigurationManager.u 
       string DataSource = cryptIT.Decrypt(cn.DataSource_bio); 
       string initialCatalog = cryptIT.Decrypt(cn.InitialCatalog_bio); 
       string user = cryptIT.Decrypt(cn.user_bio); 
       string password = cryptIT.Decrypt(cn.password_bio); 
       bool intergratedSecurity = cn.IntegratedSecurity_bio; 

       if (intergratedSecurity) 
       { 
        connectString = "Data Source=" + DataSource + ";Initial Catalog=" + initialCatalog + ";Integrated Security=True"; 
       } 
       else 
       { 
        connectString = "Data Source=" + DataSource + ";Initial Catalog=" + initialCatalog + ";User ID=" + user + ";Password=" + password; 
       } 

       NewCon3 = new SqlConnection(connectString); 
       NewCon3.Open(); 



       newCmd2 = NewCon3.CreateCommand(); 
       newCmd2.Connection = NewCon3; 
       newCmd2.CommandType = CommandType.Text; 
       newCmd2.CommandText = @" 
           SELECT [nUserID] 
             ,[sUserName] 
             ,dateadd(s,[nDateTime],'1970/1/1') AS LogDateTime 
             ,[nEventIdn] 
             ,[nTNAEvent] 
             ,[TB_READER].[nReaderIdn] 
             ,[sName] 
           FROM 
             [TB_EVENT_LOG] 
             ,[TB_USER] 
             ,[TB_READER] 
           WHERE 

             [nEventLogIdn] = " + nEventLogIdn + 
             @" AND 
             [TB_EVENT_LOG].[nUserID] = [TB_USER].[sUserID] 
             AND 
             [nFlag]= 1 
             AND 
             [TB_EVENT_LOG].[nReaderIdn]=[TB_READER].[nReaderIdn]" 
             ; 
       dr = newCmd2.ExecuteReader(); 

       if (dr != null && dr.Read()) 
       { 
        lgEntObj.nUserID = dr.GetInt32(0); 
        lgEntObj.nUserName = dr.GetString(1); 
        lgEntObj.LogDateTime = dr.GetDateTime(2); 
        lgEntObj.nEventIdn = dr.GetInt32(3); 
        lgEntObj.nTNAEvent = dr.GetInt16(4); 
        lgEntObj.nReaderIdn = dr.GetInt32(5); 
        lgEntObj.sName = dr.GetString(6); 
       } 
       dr.Close(); 
       newCmd2.Dispose(); 
       // NewCon.Close(); 
       NewCon3.Close(); 

       return lgEntObj; 
      } 
      catch (Exception exc) 
      { 
       CenUtility.ErrorLog.CreateLog(exc); 
       return null; 
      } 

      finally 
      { 
       if (dr != null) 
        dr.Close(); 

       if(newCmd2 != null) 
        newCmd2.Dispose(); 


        NewCon3.Close(); 


      } 


     } 
    } 

अग्रिम धन्यवाद देता

+0

आप इस उत्तर में दिए गए सुझावों पर विचार करना चाहते हो सकता है: http://stackoverflow.com/questions/2382410/sql-server-deadlock-fix-force-join-order-or-automatically-retry। यदि मूल क्वेरी डेडलॉक की गई है तो हमने क्वेरी रीट्रीज़ सफलतापूर्वक कार्यान्वित की है। – dash

+0

इसके अलावा, आप कितने लॉग प्रविष्टियां लिख रहे हैं? यदि आप बहुत कुछ लिख रहे हैं, तो हो सकता है कि आप बड़ी संख्या में INSERTS के साथ चयन को रोक रहे हों। – dash

+0

इस एप्लिकेशन द्वारा उन तालिकाओं में कुछ भी लिखा नहीं गया है, लेकिन एक और सॉफ्टवेयर उन तालिकाओं में डेटा लिखता है। –

उत्तर

13

आप कुछ और उपयोगी सुझावों के लिए इस question का उल्लेख करना चाह सकते हैं।

मैं डेटाबेस रीट्रीज़ के लिए निम्न पैटर्न का उपयोग करता हूं; इस उदाहरण में, हम डेटाटेबल लौटाते हैं लेकिन पैटर्न समान है; आप SqlException Number पर आधारित SqlDeadlock या टाइमआउट का पता लगाते हैं, और अधिकतम संख्या में एन बार तक पुनः प्रयास करें।

public DataTable DoSomeSql(int retryCount = 1) 
    { 
     try 
     { 
      //Run Stored Proc/Adhoc SQL here 

     } 
     catch (SqlException sqlEx) 
     { 
      if (retryCount == MAX_RETRY_COUNT) //5, 7, Whatever 
      { 
       log.Error("Unable to DoSomeSql, reached maximum number of retries."); 
       throw; 
      } 

      switch (sqlEx.Number) 
      { 
       case DBConstants.SQL_DEADLOCK_ERROR_CODE: //1205 
        log.Warn("DoSomeSql was deadlocked, will try again."); 
        break; 
       case DBConstants.SQL_TIMEOUT_ERROR_CODE: //-2 
        log.Warn("DoSomeSql was timedout, will try again."); 
        break; 
       default: 
        log.WarnFormat(buf.ToString(), sqlEx); 
        break; 
      } 

      System.Threading.Thread.Sleep(1000); //Can also use Math.Rand for a random interval of time 
      return DoSomeSql(asOfDate, ++retryCount); 
     } 
    } 
+3

मुझे आशा है कि आप इसकी निगरानी कर रहे हैं। यदि, उदाहरण के लिए, आपको एक लाख डेकॉक मिलते हैं, हर लाख प्रश्न, या प्रति माह, तो आप ठीक हैं। यदि आपको हर मिनट 1 या हर दूसरी क्वेरी मिलती है, तो आप परेशानी में हैं और इसके आसपास काम करने के बजाय कारण को ठीक करना चाहिए ... – MatBailie

+0

@Dems कभी-कभी आपको डेडलॉक मिलता है लेकिन आप नहीं चाहते कि आपका एप्लिकेशन मर जाए क्योंकि इसका पुनः प्रयास आपको समस्या के मूल कारण की जांच करने के लिए आवश्यक समय खरीदता है; ध्यान दें कि मैं पहला लिंक पढ़ने का सुझाव देता हूं :-) कभी-कभी आपको सिस्टम में व्यस्त होने के कारण डेडलॉक या टाइमआउट भी मिलता है। – dash

+0

मैं यह नहीं कह रहा हूं कि मैं ऐसा नहीं कर रहा हूं, मैं बस इसकी निगरानी करने के लिए कह रहा हूं। जैसा कि मैंने कहा, अगर यह कम है तो आप अच्छे हैं। लेकिन अगर यह नियमित है तो आपको एक समस्या है और आपने इसे एक चुप विफलता में मजबूर कर दिया है - उस समय ऐप के लिए अच्छा है, लेकिन फिर इसका मतलब है कि आपको निगरानी के किसी तरीके की आवश्यकता है कि क्या ऐसा होता है कि आपको वास्तव में पता होना चाहिए अंतर्निहित कारण और न केवल इसका प्रभाव। यदि आप निगरानी नहीं करते हैं तो आप यह भी नहीं जानते कि जांच करने के लिए कुछ भी है। – MatBailie

3

आपकी क्वेरी किसी अन्य क्वेरी के साथ deadlocked। अन्य क्वेरी सबसे अधिक संभावना है insert, update या delete क्वेरी, क्योंकि select अकेले ही डेडलॉक नहीं होता है।

FROM 
    [TB_EVENT_LOG] with (nolock) 
    ,[TB_USER] with (nolock) 
    ,[TB_READER] with (nolock) 

कि आपकी क्वेरी का कारण होगा ताले जगह नहीं:

आप स्थिरता के बारे में बहुत ज्यादा परवाह नहीं है, तो आप with (nolock) संकेत का उपयोग कर सकते हैं। ताले के बिना एक प्रश्न deadlocks का कारण नहीं होगा। नकारात्मकता यह है कि यह असंगत डेटा लौटा सकता है, जब यह एक संशोधन क्वेरी के रूप में एक ही समय में चलता है।

+0

ध्यान दें कि यदि लॉक एक टेबल लॉक में बढ़ गया है, तो यह काम नहीं करेगा; http://msdn.microsoft.com/en-us/library/ms187373.aspx देखें। – dash

+0

@ डैश: यह आलेख केवल डीडीएल पर लागू होता है, जैसे कि 'तालिका बदलें', जो एक श-एम (स्कीमा संशोधन) लॉक प्राप्त करता है। ए '(नोलॉक)' के साथ 'tablockx) ' – Andomar

+0

के साथ खुशी से पढ़ा जाएगा" अद्यतन या DELETE कथन की लक्ष्य तालिका पर लागू होने वाले FROM खंड में READUNCOMMITTED और NOLOCK संकेतों के उपयोग के लिए समर्थन को हटा दिया जाएगा SQL सर्वर का भविष्य संस्करण। इस संदर्भ में नए संकेतों के काम में इन संकेतों का उपयोग करने से बचें, और उन अनुप्रयोगों को संशोधित करने की योजना बनाएं जो वर्तमान में उनका उपयोग करते हैं। " उसमें भी है। मुझे 100% यकीन नहीं है कि यह सभी मामलों में एक लेनदेन के माध्यम से पढ़ा जाएगा; मेरे पास ऐसी स्थितियां थीं जहां नोलॉक काम नहीं करता है क्योंकि एक टेबललॉक जगह पर है। – dash

संबंधित मुद्दे