Linq to sql 具有nservicebus表锁问题的linq到sql

Linq to sql 具有nservicebus表锁问题的linq到sql,linq-to-sql,timeout,locking,nservicebus,Linq To Sql,Timeout,Locking,Nservicebus,我正在使用NServiceBus构建一个系统,我的数据层使用LINQ2SQL 该系统由2个服务组成 Service1从NSB接收消息。 它将在我的数据库中查询表1 并在表1中插入一条记录 如果满足特定条件,将向第二个服务发送新的NSB消息 当Service2从Service1接收消息并执行一些其他与数据库无关的工作时,它也将更新表1中的记录。 Service2是一个长期运行的进程 我遇到的问题是,当Service2更新表1中的记录时,表被锁定。在Service2完成所有正在处理的操作之前,该锁似

我正在使用NServiceBus构建一个系统,我的数据层使用LINQ2SQL

该系统由2个服务组成

Service1从NSB接收消息。 它将在我的数据库中查询表1 并在表1中插入一条记录 如果满足特定条件,将向第二个服务发送新的NSB消息

当Service2从Service1接收消息并执行一些其他与数据库无关的工作时,它也将更新表1中的记录。 Service2是一个长期运行的进程

我遇到的问题是,当Service2更新表1中的记录时,表被锁定。在Service2完成所有正在处理的操作之前,该锁似乎一直存在。 i、 e.释放我的datacontext后,锁不会被释放

这会导致Service1中的查询超时。 一旦Service2完成处理,Service1将毫无问题地再次恢复处理

例如,Service1代码可能如下所示:

int x =0;
using (DataContext db = new DataContext())
{
  x = (from dp in db.Table1 select dp).Count(); // this line will timeout while service2 is processing

  Table1 t = new Table1();
  t.Data = "test";
  db.Table1.InsertOnSubmit(t);
  db.SubmitChanges();
}

if(x % 50 == 0)
  CallService2();
using (DataContext db = new DataContext())
{
  Table1 t = db.Table1.Where(t => t.id == myId);
  t.Data = "updated";

  db.SubmitChanges();

}

// I would have expected the lock to have been released at this point, but this is not the case.

DoSomeLongRunningTasks();

// lock will be released once service2 exits
service2中的代码可能如下所示:

int x =0;
using (DataContext db = new DataContext())
{
  x = (from dp in db.Table1 select dp).Count(); // this line will timeout while service2 is processing

  Table1 t = new Table1();
  t.Data = "test";
  db.Table1.InsertOnSubmit(t);
  db.SubmitChanges();
}

if(x % 50 == 0)
  CallService2();
using (DataContext db = new DataContext())
{
  Table1 t = db.Table1.Where(t => t.id == myId);
  t.Data = "updated";

  db.SubmitChanges();

}

// I would have expected the lock to have been released at this point, but this is not the case.

DoSomeLongRunningTasks();

// lock will be released once service2 exits
我不明白为什么在Service2中释放datacontext时锁没有被释放

为了解决这个问题,我一直在打电话:

db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
这很有效,但我不喜欢用它。 我想妥善解决这个问题

以前有没有人遇到过这种问题,有人知道如何解决它吗? 为什么在释放datacontext后锁没有释放

提前谢谢

p、 很抱歉,这篇文章太长了

编辑:

在现实世界(ish)情况下(如航运)观察这一点:

service1将板条箱记录添加到数据库中。 将板条箱添加到集装箱记录中(如果不存在集装箱记录,则创建一条) 如果存在特定数量或板条箱记录,则创建装运记录并关闭所有集装箱并分配给装运记录

然后调用service2处理发货记录。 对service2的调用是一个Bus.Send调用,但可能是一个传奇的一部分。 服务2将更新分配给它的每个板条箱记录。 然后处理其他一些装运指示。
当service2正在处理时,下一次装运可能会收到更多板条箱,但在service2完成装运处理之前,无法将它们分配给集装箱。

您看到这种行为的原因是NServiceBus使用的默认隔离级别(与TransactionScope相同)是可序列化的-它锁定整个表

您要做的是在NServiceBus级别设置不同的隔离级别

为此,您需要使用fluent初始化API,并在调用.MsmqTransport()后调用.IsolationLevel(IsolationLevel.ReadCommitted)方法或传递其他值。我不建议低于这个标准(比如读未提交)

在上面描述的场景中,我不会将所有这些都放在一个处理程序中,而是更喜欢使用一个传奇来管理顶级流,因为您似乎很乐意在处理程序中间打破隔离边界


希望这会有所帮助。

您看到这种行为的原因是,NServiceBus使用的默认隔离级别(与TransactionScope相同)是可序列化的,这会锁定整个表

您要做的是在NServiceBus级别设置不同的隔离级别

为此,您需要使用fluent初始化API,并在调用.MsmqTransport()后调用.IsolationLevel(IsolationLevel.ReadCommitted)方法或传递其他值。我不建议低于这个标准(比如读未提交)

在上面描述的场景中,我不会将所有这些都放在一个处理程序中,而是更喜欢使用一个传奇来管理顶级流,因为您似乎很乐意在处理程序中间打破隔离边界


希望能有所帮助。

非常感谢。这正是我所需要的。实际上,将NSB级别的隔离级别更改为readcommitted并不能改善情况。我仍然遇到同样的问题。然后,您需要查看数据库中的执行计划,看看是否缺少导致全表扫描的索引,从而升级了锁。非常感谢。这正是我所需要的。实际上,将NSB级别的隔离级别更改为readcommitted并不能改善情况。我仍然遇到同样的问题。然后,您需要查看数据库中的执行计划,以查看是否缺少导致完整表扫描的索引,从而升级锁。