2017-04-26 79 views
10

我有TcpListener類,我正在使用async/await讀寫。C#Mysql的使用鎖定數據庫查詢異步等待服務器

對於此服務器,我創建了單個數據庫實例,我準備了所有數據庫查詢。

但對於更多然後一個TcpClient,我不斷收到異常:

MySql.Data.MySqlClient.MySqlException類型的異常在MySql.Data.dll發生 但在用戶代碼中沒有處理

其他信息:已經有一個打開DataReader關聯 與此Connection必須首先關閉。

如果我的理解正確,那麼不能再有一個數據庫查詢在多於一個客戶端出現問題。

所以我只是在我這樣的查詢中添加了鎖,一切似乎都很好。

// 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; 
} 

我也曾經嘗試該方法以從SO社區有人提及,但這種方法比鎖更慢,其創建的每個查詢新的連接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內執行的,這是+ - 只有網絡延遲,但是使用它是+ - 55ms,因爲.Open()方法需要+ - 35ms。

爲什麼很多人使用使用方法,如果性能差得多?或者我做錯了什麼?

+0

你有沒有[啓用MARS](https://www.connectionstrings.com/sqlconnection/enable-mars/)並設置[異步處理](https://www.connectionstrings.com/sqlconnection/asynchronous-processing/ )在你的連接字符串? –

+0

@Paulo Morgado我有MySQL而不是SQL。 MySQL沒有像我在谷歌上發現的MARS。 –

+1

而不是鎖爲什麼不打開另一個連接? – JSteward

回答

8

你說得對,打開連接是一個耗時的操作。爲了減輕這一點,ADO.NET具有連接池。詳情請查詢this article

如果繼續進行性能測試並檢查後續連接的時間安排,則應該看到connection.Open()的時間改善並接近0毫秒,因爲連接實際上是從池中獲取的。

隨着您的鎖定實現,您實際上只使用一個連接使用連接池。雖然這種方法可以在一個簡單的測試中顯示出更好的性能,但它在高負載應用程序中會顯示非常差的結果。

+0

我會試着去測試它。 –

+1

除此之外,可能值得添加一個使用ORM的提及,其中已經爲您構建了這種類型的工作(上下文實例中的連接池處理)。 – War

+0

我同意,與使用ADO.NET連接池相比,高併發應用程序中的單個鎖定會顯示可怕的性能。 –