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。
为什么很多人使用使用方法,如果性能差得多?或者我做错了什么?
你说得对,打开连接是一个耗时的操作。为了减轻这一点,ADO.NET具有连接池。详情请查询this article。
如果继续进行性能测试并检查后续连接的时间安排,则应该看到connection.Open()
的时间改善并接近0毫秒,因为连接实际上是从池中获取的。
随着您的锁定实现,您实际上只使用一个连接使用连接池。虽然这种方法可以在一个简单的测试中显示出更好的性能,但它在高负载应用程序中会显示非常差的结果。
我会试着去测试它。 –
除此之外,可能值得添加一个使用ORM的提及,其中已经为您构建了这种类型的工作(上下文实例中的连接池处理)。 – War
我同意,与使用ADO.NET连接池相比,高并发应用程序中的单个锁定会显示可怕的性能。 –
你有没有[启用MARS](https://www.connectionstrings.com/sqlconnection/enable-mars/)并设置[异步处理](https://www.connectionstrings.com/sqlconnection/asynchronous-processing/ )在你的连接字符串? –
@Paulo Morgado我有MySQL而不是SQL。 MySQL没有像我在谷歌上发现的MARS。 –
而不是锁为什么不打开另一个连接? – JSteward