2017-04-26 11 views
10

मेरे पास TcpListener वर्ग है और मैं async/await पढ़ने और लिखने का उपयोग कर रहा हूं।सी # MySQL - async प्रतीक्षा सर्वर के लिए डेटाबेस क्वेरी पर ताले का उपयोग

इस सर्वर के लिए मैंने एकल डेटाबेस उदाहरण बनाया है जहां मैंने सभी डेटाबेस क्वेरी तैयार की हैं।

लेकिन के लिए एक से अधिक TcpClient मैं कर रहा हूँ हो रही अपवाद रखें:

प्रकार MySql.Data.MySqlClient.MySqlException की एक अपवाद MySql.Data.dll में गई थी, लेकिन उपयोगकर्ता कोड में संभाला नहीं गया था

अतिरिक्त जानकारी: वहाँ पहले से ही है इस Connection के साथ DataReader संबंधित को खोलें जो पहले बंद होना चाहिए।

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

तो मैंने बस इस तरह के अपने प्रश्नों में ताले जोड़े और सबकुछ ठीक लगता है।

// One MySqlConnection instance for whole program. 

    lock (thisLock) 
    { 
    var cmd = connection.CreateCommand(); 

    cmd.CommandText = "SELECT Count(*) FROM logins WHERE username = @user AND password = @pass"; 
    cmd.Parameters.AddWithValue("@user", username); 
    cmd.Parameters.AddWithValue("@pass", password); 

    var count = int.Parse(cmd.ExecuteScalar().ToString()); 
    return count > 0; 
} 

मैं भी usings जो प्रत्येक क्वेरी के लिए नए कनेक्शन बनाने के रूप में इतना समुदाय के किसी से उल्लेख किया, लेकिन इस विधि ताले तुलना में बहुत अधिक धीमी है साथ विधि का प्रयास:

using (MySqlConnection connection = new MySqlConnection(connectionString)) 
    { 
     connection.Open(); // This takes +- 35ms and makes worse performance than locks 

     using (MySqlCommand cmd = connection.CreateCommand()) 
     { 
      cmd.CommandText = "SELECT Count(*) FROM logins WHERE username = @user AND password = @pass"; 
      cmd.Parameters.AddWithValue("@user", username); 
      cmd.Parameters.AddWithValue("@pass", password); 

      int count = int.Parse(cmd.ExecuteScalar().ToString()); 
      return count > 0; 
     } 
    } 

मैं करने के लिए इस्तेमाल किया स्टॉपवॉच ताले के साथ एक कनेक्शन के साथ इस विधि और प्रश्नों को बेंचमार्क + - 20ms में किया जाता है जो + - केवल नेटवर्क की देरी है, लेकिन उपयोग के साथ यह .Open() विधि के कारण + - 55ms है जो + - 35ms लेता है।

यदि बहुत खराब प्रदर्शन होता है तो बहुत से लोग उपयोग के साथ विधि का उपयोग क्यों करते हैं? या मुझ से कुछ गलत हो रहा है?

+0

क्या आपने [सक्षम मार्स] (https://www.connectionstrings.com/sqlconnection/enable-mars/) सेट किया है और [एसिंक्रोनस प्रोसेसिंग] सेट किया है (https://www.connectionstrings.com/sqlconnection/asynchronous-processing/) आपके कनेक्शन स्ट्रिंग पर? –

+0

@ पाउलो मोर्गैडो मेरे पास MySQL एसक्यूएल नहीं है। MySQL में एमएआरएस नहीं है जैसा कि मैंने Google पर पाया था। –

+1

लॉक के बजाय क्यों एक और कनेक्शन नहीं खोलें? – JSteward

उत्तर

8

आप सही हैं, कनेक्शन खोलने का समय लेने वाला ऑपरेशन है। इसे कम करने के लिए, ADO.NET में कनेक्शन पूलिंग है। विवरण के लिए this article देखें।

यदि आप अपने प्रदर्शन परीक्षण के साथ जाते हैं और बाद के कनेक्शन के लिए समय की जांच करते हैं, तो आपको यह देखना चाहिए कि connection.Open() के लिए उस समय में सुधार होता है और 0 एमएस के करीब आता है क्योंकि कनेक्शन वास्तव में पूल से लिया जाता है।

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

+0

मैं इसका परीक्षण करने की कोशिश करूंगा। –

+1

इसके अतिरिक्त यह एक ओआरएम का उपयोग करने का उल्लेख जोड़ने लायक है जहां इस प्रकार का काम पहले से ही आपके लिए बनाया गया है (संदर्भ उदाहरणों के भीतर कनेक्शन पूल हैंडलिंग)। – War

+0

मैं मानता हूं, अत्यधिक समवर्ती एप्लिकेशन में एक लॉक ADO.NET कनेक्शन पूलिंग का उपयोग करने की तुलना में भयानक प्रदर्शन दिखाएगा। –

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