在多线程上执行相互依赖的数据库操作

时间:2013-03-13 11:54:18

标签: c# sql multithreading parallel-processing

我用C#编写的服务器应用程序每次需要插入或删除数据库中的数据时都会启动一个新线程。问题在于,由于线程的执行是任意的,因此如果这些事件几乎同时发生,则无法确保在插入相同对象后执行删除命令。

例如:服务器接收插入多个对象的命令。插入所有对象大约需要5秒钟。执行1秒后,服务器会收到再次从数据库中删除所有这些对象的命令。由于删除可能在所有对象完全存储之前发生,因此结果是未知的。

如何管理某个线程的执行顺序?

4 个答案:

答案 0 :(得分:2)

您可以为此使用交易,并为不同的操作指定不同的级别。

例如,您可以使用最高级别的事务进行写入/更新/删除,但使用较低级别的读取。与表相比,您还可以对此进行微调以仅允许阻止特定行。 Specific terminology取决于您使用的数据库和数据访问库。

我建议不要使用任何订购。平行和有序只是不能很好地融合在一起。例如:

  • 您需要水平扩展服务器,一旦添加第二台服务器和负载均衡器,互斥解决方案将无法正常工作

  • 在大型分布式系统中,消息队列无法正常运行,因为当一个线程完成扫描并确定我们要继续运行时,另一个线程可以编写应该​​阻止操作执行的消息。此外,如果您收到高负载,多次扫描同一队列效率低下。

答案 1 :(得分:0)

如果您知道在删除之前收到插入,问题只是您不想中断插入,那么您可以使用锁定插入代码。

static object m_Lock = new object();

public void Insert()    
{
   lock (m_Lock)
   {
      InsertRecords();
   }
}

public void Remove()    
{
   lock (m_Lock)
   {
      RemoveRecords();
   }
}

这样您就可以确保在插入过程中不会发生删除。

P.S。虽然您需要立即插入然后删除,但似乎很奇怪。

答案 2 :(得分:0)

我认为最简单的方法是将所有传入请求排队到一个集合中插入对象,并将所有传入请求排入队列以删除第二个集合中的对象。

服务器应该有一个基本循环:

<强>一个。检查是否有传入插入,如果是 - &gt;执行所有插入。

<强>湾检查是否有传入的删除请求,如果是 - &gt;执行所有删除请求。

<强>℃。睡了X毫秒。

现在,如果您对不存在的对象有删除请求。 你有两个选择:

<强>一个。请求此请求并将其丢弃。

<强>湾忽略此回合的此请求并将其保留在接下来的N轮中的集合中, 在删除之前(最后删除它 - 假设这只是一个错误的请求而不是竞争条件的问题。)

答案 3 :(得分:0)

使用队列(使用单个服务线程)来强制执行排序。您还可以使用任务并行库来管理具有其他任务依赖性的任务,但这对于任意数据库操作来说非常困难。

我认为你需要重新思考如何管理传入的操作,以及它们的相互依赖性是否足够可预测,以便以这种方式安全地使用多个线程。您可能需要在传入的操作中添加一些“依赖”信息才能实现该目标。