मैं ASP.NET और SQL सर्वर के बीच कनेक्शन पूल समस्या को कैसे हल कर सकता हूं?


211

पिछले कुछ दिनों से हमें अपनी वेबसाइट में यह त्रुटि संदेश दिखाई दे रहा है:

"समय समाप्त हो गया है। पूल से कनेक्शन प्राप्त करने से पहले का समय समाप्त हो गया है। ऐसा हो सकता है क्योंकि सभी पूल किए गए कनेक्शन उपयोग में थे और अधिकतम पूल आकार तक पहुँच गया था।"

हमने कुछ समय में अपने कोड में कुछ भी नहीं बदला है। मैंने खुले कनेक्शन की जांच करने के लिए कोड को संशोधित किया, जो बंद नहीं हुआ, लेकिन सब कुछ ठीक पाया गया।

  • इसे कैसे हल किया जा सकता है?

  • क्या मुझे इस पूल को संपादित करने की आवश्यकता है?

  • मैं इस पूल की अधिकतम संख्या को कैसे संपादित कर सकता हूं?

  • उच्च ट्रैफ़िक वेबसाइट के लिए अनुशंसित मूल्य क्या है?


अपडेट करें:

क्या मुझे IIS में कुछ संपादित करने की आवश्यकता है?

अपडेट करें:

मैंने पाया कि सक्रिय कनेक्शन की संख्या 15 से 31 के बीच कहीं भी है, और मैंने पाया कि SQL सर्वर में कॉन्फ़िगर किए गए कनेक्शन की अधिकतम अनुमत संख्या 3200 से अधिक कनेक्शन है, 31 बहुत अधिक है या मुझे ASP.NET कॉन्फ़िगरेशन में कुछ संपादित करना चाहिए ?


अगर मुझे सही से याद है तो मैक्स पूल साइज डिफ़ॉल्ट 100 है। अधिकांश वेब साइट्स भारी लोड के तहत 50 से अधिक कनेक्शन का उपयोग नहीं करती हैं - यह निर्भर करता है कि आपके प्रश्नों को पूरा करने में कितना समय लगता है। कनेक्शन स्ट्रिंग में शॉर्ट टर्म फिक्स: अपने कनेक्शन स्ट्रिंग्स में एक उच्च मूल्य सेट करने का प्रयास करें: "मैक्स पूल का आकार = ..."
splattne

कितना? उदाहरण के लिए इसे 200 करें?
अमृत ​​एल्गारहि

3
मुझे लगता है कि आपको वास्तव में इस बात की खोज करनी चाहिए कि समस्या क्या है। क्या आपके प्रश्न (या उनमें से कुछ) बहुत लंबे समय से चल रहे हैं?
13:22

यह वास्तविक कारण हो सकता है, एक क्वेरी जिसे निष्पादित करने में बहुत समय लग रहा है, मैं उस में खोज करूंगा, धन्यवाद
अमृत ​​एलगारही

1
मुझे उम्मीद है कि आप समस्या पा सकते हैं। एक सुझाव: यदि आप SQL सर्वर का उपयोग कर रहे हैं, तो "SQL Profiler" आज़माएँ और लंबे प्रश्नों की तलाश करें: sql-server-performance.com/articles/per/…
splattne

जवाबों:


218

ज्यादातर मामलों में कनेक्शन पूलिंग समस्याएं "कनेक्शन लीक" से संबंधित हैं। आपका एप्लिकेशन संभवतः अपने डेटाबेस कनेक्शन को सही और लगातार बंद नहीं करता है। जब आप कनेक्शन को खुला छोड़ देते हैं, तो वे तब तक अवरुद्ध रहते हैं जब तक कि .NET कचरा कलेक्टर उन्हें अपने Finalize()तरीके से कॉल करके आपके लिए बंद नहीं कर देता ।

आप यह सुनिश्चित करना चाहते हैं कि आप वास्तव में कनेक्शन बंद कर रहे हैं । उदाहरण के लिए निम्नलिखित कोड कनेक्शन रिसाव का कारण होगा, अगर कोड अपवाद के बीच .Openऔर Closeफेंकता है:

var connection = new SqlConnection(connectionString);
connection.Open();
// some code
connection.Close();                

सही तरीका यह होगा:

var connection = new SqlConnection(ConnectionString);
try
{
     connection.Open();
     someCall (connection);
}
finally
{
     connection.Close();                
}

या

using (SqlConnection connection = new SqlConnection(connectionString))
{
     connection.Open();
     someCall(connection);
}

जब आपका फ़ंक्शन एक क्लास विधि से कनेक्शन देता है, तो सुनिश्चित करें कि आप इसे स्थानीय रूप से कैश करते हैं और इसकी Closeविधि कहते हैं । आप उदाहरण के लिए इस कोड का उपयोग करके एक कनेक्शन लीक करेंगे:

var command = new OleDbCommand(someUpdateQuery, getConnection());
result = command.ExecuteNonQuery();
connection().Close(); 

कनेक्शन पहली कॉल से वापस आ गया getConnection() बंद नहीं किया जा रहा है। आपके कनेक्शन को बंद करने के बजाय, यह रेखा एक नया निर्माण करती है और इसे बंद करने का प्रयास करती है।

यदि आप उपयोग करते हैं SqlDataReaderया ए OleDbDataReader, उन्हें बंद करें। भले ही कनेक्शन को बंद करना ही चाल को लगता है, अपने डेटा रीडर ऑब्जेक्ट्स को स्पष्ट रूप से बंद करें जब आप उनका उपयोग करते हैं।


यह लेख " क्यों एक कनेक्शन पूल अतिप्रवाह करता है?MSDN / SQL पत्रिका से " बहुत सारे विवरणों की व्याख्या करता है और कुछ डीबगिंग रणनीतियों का सुझाव देता है:

  • भागो sp_whoया sp_who2। ये सिस्टम संग्रहीत कार्यविधियाँ sysprocessesसिस्टम तालिका से जानकारी लौटाती हैं जो सभी कार्य प्रक्रियाओं के बारे में और स्थिति की जानकारी दिखाती है। आम तौर पर, आपको प्रति कनेक्शन एक सर्वर प्रक्रिया आईडी (एसपीआईडी) दिखाई देगी। यदि आपने कनेक्शन स्ट्रिंग में एप्लिकेशन नाम तर्क का उपयोग करके अपने कनेक्शन का नाम दिया है, तो आपके काम के कनेक्शन खोजने में आसान होंगे।
  • TSQL_Replayखुला कनेक्शन का पता लगाने के लिए SQLProfiler टेम्पलेट के साथ SQL सर्वर प्रोफाइलर का उपयोग करें । यदि आप Profiler से परिचित हैं, तो यह विधि sp_who का उपयोग करके मतदान से अधिक आसान है।
  • पूल और कनेक्शन की निगरानी के लिए प्रदर्शन मॉनिटर का उपयोग करें। मैं इस विधि पर एक क्षण में चर्चा करता हूं।
  • कोड में प्रदर्शन काउंटरों की निगरानी करें। आप अपने कनेक्शन पूल के स्वास्थ्य और काउंटरों को निकालने के लिए रूटीन का उपयोग करके या नए .NET PerformanceCounter नियंत्रणों का उपयोग करके स्थापित कनेक्शनों की संख्या की निगरानी कर सकते हैं।

4
एक छोटा सुधार: जीसी कभी किसी वस्तु के निपटान के तरीके को नहीं कहता है, केवल इसका अंतिम रूप (यदि एक है)। यदि आवश्यक हो, तो अंतिम रूप से डिस्पोज़ करने के लिए "फ़ॉलबैक" कॉल कर सकते हैं, हालांकि मैं निश्चित नहीं हूं कि SqlConnection ऐसा करता है या नहीं।
ल्यूक

1
क्या किसी प्रकार का प्रदर्शन गिरावट है जब हमें मैक्स पूल का आकार 50 सेट करना है और हमारे पास केवल कुछ उपयोगकर्ता हैं।
महेश शर्मा

37

.NET फ्रेमवर्क स्थापित करने पर v4.6.1 एक दूरस्थ डेटाबेस के लिए हमारे कनेक्शन तुरंत इस बदलाव के कारण समय समाप्त हो गया

TransparentNetworkIPResolutionकनेक्शन स्ट्रिंग में बस पैरामीटर जोड़ने के लिए इसे ठीक करने के लिए इसे गलत पर सेट करें :

सर्वर = myServerName; डाटाबेस = myDataBase; Trusted_Connection यह सच है =; TransparentNetworkIPResolution झूठी =


इस मामले में मुद्दा यह है "पूल से कनेक्शन प्राप्त करने से पहले का समय समाप्त हो गया है"। क्या आपके कनेक्शन स्ट्रिंग फिक्स ने इसे हल किया था, या यह एक अलग हैंडशेकिंग मुद्दा था?
FBryant87

1
मुझे जो याद है, वह प्रश्न में ठीक उसी त्रुटि संदेश के रूप में था। .NET फ्रेमवर्क v4.6.1 को अपडेट करने के तुरंत बाद यह हुआ।
अंजबिएन

मेरे लिए भी यही स्थिति थी, मेरे लिए यह तय था कि मैं एक ऐप सेवा पर चल रहा था जो मैं Azure पर चल रहा था, एक Azure SQL डेटाबेस के कनेक्शन के लिए। मैं डैपर का उपयोग कर रहा था और कनेक्शन का सही तरीके से निपटारा कर रहा था, फिर भी "पूल से एक कनेक्शन प्राप्त करने से पहले समय समाप्त हो गया" त्रुटि संदेश मिला। लेकिन और नहीं, इसलिए धन्यवाद @ajbeaven
स्टीव केनेयर्ड

13

जब तक आपका उपयोग बहुत अधिक नहीं हो जाता, तब तक यह संभव नहीं लगता है कि काम का एक बैकलॉग है। IMO, सबसे संभावित विकल्प यह है कि कुछ कनेक्शन का उपयोग कर रहा है और उन्हें तुरंत जारी नहीं कर रहा है। क्या आप वाकईusing सभी मामलों में उपयोग कर रहे हैं ? या (जो भी तंत्र के माध्यम से) कनेक्शन जारी कर रहा है?


13

क्या आपने DataReaders की जांच की है जो बंद नहीं हुए हैं और कनेक्शन बंद करने से पहले प्रतिक्रिया दे रहे हैं। जब आप उन्हें रीडायरेक्ट से पहले बंद नहीं करते हैं तो कनेक्शन खुले रहते हैं।


3
+1 - या फ़ंक्शंस DataReaders - कनेक्शन आपके द्वारा बनाए गए फ़ंक्शन के बाहर कभी भी बंद नहीं होगा ...
splattne

1
यदि आपका फ़ंक्शन SqlDataReader देता है, तो आप इसे अधिकतम पूल आकार बढ़ाने की तुलना में DataTable में परिवर्तित करना बेहतर मानते हैं
Live-love

10

हम समय-समय पर अपनी वेब साइट पर इस समस्या का सामना करते हैं। हमारे मामले में अपराधी, हमारे आँकड़े / सूचकांक तारीख से बाहर हो रहे हैं। यह पहले से तेज़ चलने वाली क्वेरी का कारण बनता है (अंततः) धीमा और समय समाप्त हो जाता है।

आंकड़ों को अपडेट करने और / या क्वेरी से प्रभावित तालिकाओं पर अनुक्रमणिका के पुनर्निर्माण का प्रयास करें और देखें कि क्या मदद करता है।


3
मुझे लगता है कि यह समझाता है कि कोई प्रश्न क्यों समाप्त हो सकता है, लेकिन मुझे नहीं लगता कि यह समझाएगा कि कनेक्शन प्राप्त करने का प्रयास करते समय एक समय का अनुभव क्यों होता है।
Drrriff

1
यह हो सकता है कि एक खराब सूचकांक के साथ प्रश्नों में अधिक समय लगे और एक ही समय में अधिक कनेक्शन का उपयोग किया जाए।
लॉसमनोस

1
Db पर sp_updatestats के साथ सभी आँकड़े अपडेट करने के बाद मेरे लिए काम किया: EXEC sp_updatestats;
नावेंग

6

आप न्यूनतम और अधिकतम पूल आकार निर्दिष्ट कर सकते हैं MinPoolSize=xyzऔर / या MaxPoolSize=xyzकनेक्शन स्ट्रिंग में। समस्या का यह कारण एक अलग बात हो सकती है।


3
अनुशंसित MaxPoolSize क्या है?
अमर एल्गरहि

2
शायद, जाने के लिए सबसे अच्छा तरीका है नहीं जब तक आप विशेष आवश्यकताएं होती हैं और आप अपने लिए एक अच्छा पूल आकार पता है कि यह निर्दिष्ट करने के लिए विशेष मामले
मेहरदाद आफश्री

1
नोट: मैंने जाँच की और मैंने पाया कि मेरे db के सक्रिय कनेक्शन लगभग 22 रहते हैं, क्या यह बहुत अधिक है?
अमृत ​​एल्गारहि

मुझे ऐसा नहीं लगता। मुझे लगता है कि डिफ़ॉल्ट पूल का आकार 100 कनेक्शन है। यह नेटवर्क और SQL सर्वर पर प्रत्येक कनेक्शन के लोड पर निर्भर करता है। यदि वे भारी क्वेरी चला रहे हैं, तो यह समस्या पैदा कर सकता है। साथ ही, नया कनेक्शन आरंभ करते समय नेटवर्क समस्याएँ हो सकती हैं और यह अपवाद का कारण बन सकता है।
मेहरदाद अफशरी 22:00

5

मुझे इस समस्या का भी सामना करना पड़ा है, जब मेरे किसी .NET अनुप्रयोग में 3 जी पार्टी डेटा परत का उपयोग किया गया है। समस्या यह थी कि परत ठीक से कनेक्शन बंद नहीं करती थी।

हमने परत को बाहर फेंक दिया और खुद को बनाया, जो हमेशा बंद हो जाता है और कनेक्शन का निपटान करता है। तब से अब हमें त्रुटि नहीं मिली है।


हम एलएलबीएल का उपयोग कर रहे हैं और वेबसाइट 2 साल से चल रही है और पिछले कुछ दिनों से इस तरह की कार्रवाई शुरू हुई है।
अमृत ​​एल्गारि

5

टाइमआउट समस्या को हल करने के लिए आप यह भी कोशिश कर सकते हैं:

यदि आपने httpRuntime को अपने webconfig में नहीं जोड़ा है, तो उसे <system.web>टैग में जोड़ें

<sytem.web>
     <httpRuntime maxRequestLength="20000" executionTimeout="999999"/>
</system.web>

तथा

अपने कनेक्शन स्ट्रिंग को इस तरह से संशोधित करें;

 <add name="connstring" connectionString="Data Source=DSourceName;Initial Catalog=DBName;Integrated Security=True;Max Pool Size=50000;Pooling=True;" providerName="System.Data.SqlClient" />

अंतिम उपयोग पर

    try
    {...} 
    catch
    {...} 
    finaly
    {
     connection.close();
    }

3

यह मुख्य रूप से आवेदन में कनेक्शन बंद नहीं होने के कारण है। कनेक्शन स्ट्रिंग में "MinPoolSize" और "MaxPoolSize" का उपयोग करें।


3

मेरे मामले में, मैं DataReader ऑब्जेक्ट को बंद नहीं कर रहा था।

        using (SqlCommand dbCmd = new SqlCommand("*StoredProcedureName*"))
        using (dbCmd.Connection = new SqlConnection(WebConfigurationAccess.ConnectionString))
            {
            dbCmd.CommandType = CommandType.StoredProcedure;

            //Add parametres
            dbCmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = ID;
.....
.....
            dbCmd.Connection.Open();
            var dr = dbCmd.ExecuteReader(); //created a Data reader here
            dr.Close();    //gotta close the data reader
            //dbCmd.Connection.Close(); //don't need this as 'using' statement should take care of this in its implicit dispose method.
            }

2

यदि आप जटिल विरासत कोड पर काम कर रहे हैं, जहाँ एक सरल (..) {..} का उपयोग संभव नहीं है - जैसा कि मैं था - आप कोड स्निपेट की जाँच कर सकते हैं जिसे मैंने इस SO प्रश्न में पोस्ट किया है ताकि यह निर्धारित किया जा सके। जब कनेक्शन संभावित रूप से लीक किया जाता है तो कनेक्शन निर्माण के कॉल स्टैक (निर्धारित समय समाप्त होने के बाद बंद नहीं)। इससे लीक के कारण का पता लगाना काफी आसान हो जाता है।


2

बहुत बार sql कनेक्शन को तुरंत न करें। एक या दो कनेक्शन खोलें और सभी अगले sql संचालन के लिए उनका उपयोग करें।

लगता है कि जब भी Disposeकनेक्शन आईएनजी अपवाद फेंक दिया है।


2

पोस्ट किए गए समाधानों के अलावा ...।

विरासत कोड के 1000 पृष्ठों के साथ काम करने में, प्रत्येक एक बार एक आम GetRS बुलाता है, यहां समस्या को ठीक करने का एक और तरीका है:

एक मौजूदा आम DLL में, हमने CommandBehavior.CloseConnection विकल्प जोड़ा :

    static public IDataReader GetRS(String Sql)
    {
        SqlConnection dbconn = new SqlConnection(DB.GetDBConn());
        dbconn.Open();
        SqlCommand cmd = new SqlCommand(Sql, dbconn);
        return cmd.ExecuteReader(CommandBehavior.CloseConnection);   
    }

तब प्रत्येक पृष्ठ में, जब तक आप डेटा रीडर बंद कर देते हैं, तब तक कनेक्शन स्वचालित रूप से बंद हो जाता है, इसलिए कनेक्शन लीक को रोका जाता है।

    IDataReader rs = CommonDLL.GetRS("select * from table");
    while (rs.Read())
    {
        // do something
    }
    rs.Close();   // this also closes the connection

2

मुझे बस वही समस्या थी और वह स्रोत साझा करने में मेरी मदद करना चाहता था: अपने कनेक्शन स्ट्रिंग में एप्लिकेशन नाम जोड़ें और फिर SQL सर्वर के लिए खुले कनेक्शन को प्रेरित करें

select st.text,
    es.*, 
    ec.*
from sys.dm_exec_sessions as es
    inner join sys.dm_exec_connections as ec on es.session_id = ec.session_id
    cross apply sys.dm_exec_sql_text(ec.most_recent_sql_handle) st
where es.program_name = '<your app name here>'

1

यह समस्या मुझे अपने कोड में थी। मैं कुछ उदाहरण कोड पेस्ट करूँगा जो मैंने खत्म कर दिए हैं त्रुटि के नीचे। समयबाह्य अवधि पूल से एक कनेक्शन प्राप्त करने से पहले समाप्त हो गई। यह हो सकता है क्योंकि सभी जमा कनेक्शन उपयोग में थे और अधिकतम पूल आकार तक पहुँच गया था।

 String query = "insert into STATION2(ID,CITY,STATE,LAT_N,LONG_W) values('" + a1 + "','" + b1 + "','" + c1 + "','" + d1 + "','" + f1 + "')";
    //,'" + d1 + "','" + f1 + "','" + g1 + "'

    SqlConnection con = new SqlConnection(mycon);
    con.Open();
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = query;
    cmd.Connection = con;
    cmd.ExecuteNonQuery();
    **con.Close();**

आप हर बार कनेक्शन बंद करना चाहते हैं। इससे पहले कि मैं इस त्रुटि के कारण हमें नज़दीकी कनेक्ट नहीं करता था। क्लोज स्टेटमेंट जोड़ने के बाद मैं इस त्रुटि पर आया हूं


0

आपने अपने कोड पर कनेक्शन लीक कर दिया है। आप यह प्रमाणित करने के लिए उपयोग करने का प्रयास कर सकते हैं कि आप उन्हें बंद कर रहे हैं।

 Using (SqlConnection sqlconnection1 = new SqlConnection(“Server=.\\SQLEXPRESS ;Integrated security=sspi;connection timeout=5”)) {
                          sqlconnection1.Open();
                          SqlCommand sqlcommand1 = sqlconnection1.CreateCommand();
                          sqlcommand1.CommandText = raiserror (‘This is a fake exception’, 17,1)”;
                          sqlcommand1.ExecuteNonQuery();  //this throws a SqlException every time it is called.
                          sqlconnection1.Close(); //Still never gets called.
              } // Here sqlconnection1.Dispose is _guaranteed_

https://blogs.msdn.microsoft.com/angelsb/2004/08/25/connection-pooling-and-the-timeout-expired-exception-faq/


0

यह समस्या मैंने पहले भी देखी है। यह फ़ायरवॉल के साथ एक मुद्दा रहा। मैंने बस फ़ायरवॉल में एक नियम जोड़ा है। मुझे पोर्ट खोलना था 1433ताकि SQL सर्वर सर्वर से कनेक्ट हो सके।


0

इसे इस्तेमाल करो:

finally
{
    connection.Close();
    connection.Dispose();
    SqlConnection.ClearPool();
}

12
हो सकता है कि मैं इस बिंदु को याद कर रहा हूं SqlConnection.ClearPool, लेकिन क्या आपके वर्तमान कनेक्शन को वापस कनेक्शन पूल में जारी करने से रोका जा सकता है? मुझे लगा कि कनेक्शन पूल का विचार त्वरित कनेक्शन की अनुमति देना था। निश्चित रूप से पूल से कनेक्शन को हर बार जारी करने का मतलब यह है कि एक नया कनेक्शन पूल से एक अतिरिक्त खींचने के बजाय, हर समय एक नया कनेक्शन बनाने की आवश्यकता होगी? कृपया बताएं कि यह तकनीक कैसे और क्यों उपयोगी है।
डिब

0

हां, कॉन्फ़िगरेशन बदलने का एक तरीका है। यदि आप एक समर्पित सर्वर पर हैं और आपको अधिक SQL कनेक्शन की आवश्यकता है, तो आप इन निर्देशों का पालन करके दोनों कनेक्शन स्ट्रिंग्स में "अधिकतम पूल आकार" प्रविष्टियों को अपडेट कर सकते हैं:

  1. रिमोट डेस्कटॉप का उपयोग करके अपने सर्वर में प्रवेश करें
  2. मेरा कंप्यूटर खोलें (Windows - E) और C: \ inetpub \ vhosts [डोमेन] \ httpdocs पर जाएं
  3. Web.config फ़ाइल पर डबल क्लिक करें। यदि एक्सटेंशन को छिपाने के लिए फ़ाइल संरचना सेट है, तो इसे केवल वेब के रूप में सूचीबद्ध किया जा सकता है। यह Visual Basic या समान संपादक को खोलेगा।
  4. अपने कनेक्शन स्ट्रिंग्स ढूंढें, ये नीचे दिए गए उदाहरणों के समान होंगे:

    "Add name =" SiteSqlServer "connectionString =" server = (local); डेटाबेस = dbname; uid = dbuser; pwd = dbpassword; पूलिंग = सही; कनेक्शन जीवनकाल = 120; अधिकतम पूल आकार = 25; ""

5. आवश्यक पूल आकार के लिए अधिकतम पूल आकार = एक्स मान बदलें।

  1. अपनी web.config फ़ाइल को सहेजें और बंद करें।

0

सुनिश्चित करें कि आपने कनेक्शन पूल के लिए सही सेटिंग्स सेट की हैं। यह बहुत महत्वपूर्ण है जैसा कि मैंने निम्नलिखित लेख में बताया है: https://medium.com/@dewanwaqas/configurations-that-significantly-improves-your-app-performance-built-using-sql-server-and-net-net ed044e53b60 यदि आप इसका पालन करते हैं तो आपको अपने आवेदन के प्रदर्शन में भारी सुधार होगा।


0

मेरे मामले में, मेरे पास अनंत लूप था (एक प्राप्त संपत्ति से डेटाबेस से मूल्य प्राप्त करने की कोशिश कर रहा था) जो सैकड़ों Sql कनेक्शन खोलता रहा।

समस्या को पुन: उत्पन्न करने के लिए यह प्रयास करें:

while (true)
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        someCall(connection);
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.