我有一个 TcpListener
类,正在使用 async/await
来读写。
对于这个服务器,我创建了单个数据库实例,其中准备了所有数据库查询。
但是,当有多个 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;
}
我也尝试了SO社区中某人提到的使用“usings”为每个查询创建新连接的方法,但是这种方法比锁定方法慢得多:
我也尝试了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,仅是网络延迟;但使用usings后执行时间约为55ms,因为.Open()
方法需要约35ms的时间。
如果性能更差,为什么很多人还要使用带usings的方法?或者是我的做法有问题吗?
connectionString = "SERVER=" + server + ";" + "DATABASE=" + database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";CHARSET=utf8mb4";
- Erik Šťastný