来自后台工作者冲突的查询?

问题描述

如果我使用相同的ConnectionString从多个线程执行查询,是否有问题?如果两个或多个线程尝试同时发送数据会怎样?

Result

解决方法

如果正确使用,则并发连接正常

假设正确的理由,并发使用多个连接没有问题。数据库可以处理数千个并发客户端连接。

并行执行相同的慢速查询以使其更快完成,可能会使它更慢,因为每个连接都可能阻塞其他连接。许多数据库已经使查询处理并行化,产生的结果比粗略的客户端并行性要好得多。

如果您想使慢速查询更快,可以通过调查慢速原因并解决性能问题来获得更好的结果。例如,如果要插入1万行,则使用SqlBulkCopy或BULK INSERT来加载行要比执行10K INSERT更快,而INSERT最终会相互阻塞以访问同一张表甚至数据页。 >

您可以使用同一连接执行异步查询(例如,使用ExecuteNonQueryAsync()ExecuteReaderAsync()等,前提是它们一个接一个地执行。您不能在同一连接上执行多个并发查询,至少不是没有经过一些箍。

真正的问题

真正的问题是首先使用BackgroundWorker。自2012年引入async/await以来,该类已过时。使用BGW,很难组合多个异步操作。进度报告可以通过Progress<T>类获得,合作取消可以通过CancellationTokenSource获得。检查Async in 4.5: Enabling Progress and Cancellation in Async APIs以获得详细说明。

您只能用await command.ExecuteNonQueryAsync()替换代码中的BGW调用。您可以创建一个异步方法来执行将数据插入数据库的操作:

private async Task InsertTestData(string serialNumber,string testResult)
{
   // if server is online,send data
   if(serverIsOnline)
   {
      using(SqlConnection connection = new SqlConnecton(globalConnectionString))
      {
         var someCommand = new SqlCommand("some insert/update command here!",connection);
         someCommand.Parameters.Add("@serial",SqlDbType.NVarChar,30).Value=serialNumber;
         ...
         connection.Open();
         Command.ExecuteNonQueryAsync();
      }
   }
}

如果检索序列号和测试数据很耗时,则可以使用Task.Run在后​​台运行它们:

   string serialNumber = await Task.Run(()=>getSerialNumber(logFile));
   string testResult = await Task.Run(()=>getTestResult(logFile));
   await InsertTestData(serialNumber,testResult);

您也可以使用Dapper之类的库来简化数据库:

private async Task InsertTestData(string serialNumber,send data
   if(serverIsOnline)
   {
      using(SqlConnection connection = new SqlConnecton(globalConnectionString))
      {
         await connection.ExecuteAsync("INSERT .... VALUES(@serial,@test)",new {serial=serialNumber,test=testResults});
      }
   }
}

Dapper将生成一个参数化查询,并按名称将查询中的参数与匿名对象中的属性进行匹配。

,

在这里读取连接字符串不是问题。如果要通过多个线程共享SqlConnection对象,则会遇到问题。但这不是您的代码中的情况。

,

我认为这是关于ACID属性中的Isolation的问题。请看看他们。

基于SQL标准,单个SQL查询在查询所处理的表的稳定(一致)状态下运行。因此,此定义规定,在执行过程中看不到任何更改。但是,据我所知,并不是所有的DBMS软件都完全遵循此规则。例如,某些产品和/或隔离级别允许脏读。

这里有另一个用户的详细explanation