Linq to sql 具有nservicebus表锁问题的linq到sql
我正在使用NServiceBus构建一个系统,我的数据层使用LINQ2SQL 该系统由2个服务组成 Service1从NSB接收消息。 它将在我的数据库中查询表1 并在表1中插入一条记录 如果满足特定条件,将向第二个服务发送新的NSB消息 当Service2从Service1接收消息并执行一些其他与数据库无关的工作时,它也将更新表1中的记录。 Service2是一个长期运行的进程 我遇到的问题是,当Service2更新表1中的记录时,表被锁定。在Service2完成所有正在处理的操作之前,该锁似乎一直存在。 i、 e.释放我的datacontext后,锁不会被释放 这会导致Service1中的查询超时。 一旦Service2完成处理,Service1将毫无问题地再次恢复处理 例如,Service1代码可能如下所示: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完成所有正在处理的操作之前,该锁似
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并不能改善情况。我仍然遇到同样的问题。然后,您需要查看数据库中的执行计划,以查看是否缺少导致完整表扫描的索引,从而升级锁。