C#Mysql的使用锁定数据库查询异步等待服务器

问题描述:

我有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

你说得对,打开连接是一个耗时的操作。为了减轻这一点,ADO.NET具有连接池。详情请查询this article

如果继续进行性能测试并检查后续连接的时间安排,则应该看到connection.Open()的时间改善并接近0毫秒,因为连接实际上是从池中获取的。

随着您的锁定实现,您实际上只使用一个连接使用连接池。虽然这种方法可以在一个简单的测试中显示出更好的性能,但它在高负载应用程序中会显示非常差的结果。

+0

我会试着去测试它。 –

+1

除此之外,可能值得添加一个使用ORM的提及,其中已经为您构建了这种类型的工作(上下文实例中的连接池处理)。 – War

+0

我同意,与使用ADO.NET连接池相比,高并发应用程序中的单个锁定会显示可怕的性能。 –