我们的SQL Server 2014数据库设置为READ_COMMITTED_SNAPSHOT。
我们使用MSMQ和分布式事务(我们使用MassTransit 2.10)。
在系统的某个部分,我们从队列中读取消息,对数据库进行更新,然后发布新消息到队列中(所有这些都在单个事务下完成)。
我们发现一种情况,即当处理下一条消息时,似乎更新没有被提交(它从第一部分更新相同的表),尽管我期望该消息仅在更新数据库时在队列上。当我们稍后查询该表时,更新的数据就像预期的那样出现了。这只会在高负载和非常罕见的情况下发生。
我们代码的简化版本
我们使用MSMQ和分布式事务(我们使用MassTransit 2.10)。
在系统的某个部分,我们从队列中读取消息,对数据库进行更新,然后发布新消息到队列中(所有这些都在单个事务下完成)。
我们发现一种情况,即当处理下一条消息时,似乎更新没有被提交(它从第一部分更新相同的表),尽管我期望该消息仅在更新数据库时在队列上。当我们稍后查询该表时,更新的数据就像预期的那样出现了。这只会在高负载和非常罕见的情况下发生。
我们代码的简化版本
// code that processes message 1
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions() { Timeout = TimeSpan.FromMinutes(30), IsolationLevel = IsolationLevel.ReadCommitted })
{
MethodThatUpdatesTableX();
MethodThatCreatesMessage2();
scope.Complete();
}
// message picked up from MSMQ and then (this runs in different thread):
// code that process message 2
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions() { Timeout = TimeSpan.FromMinutes(30), IsolationLevel = IsolationLevel.ReadCommitted })
{
MethodThatReadsFromTableX(); // so here it seems that changes made in MethodThatUpdatesTableX is sometimes (though rarely) not read
// other stuff
}
我这里的理解是:
当作用域被释放时,对表X所做的更改将被提交,并且消息将发布到队列中。
当MethodThatReadsFromTableX()
从表X中读取数据时,我期望更改已经存在(会话不应在第一个会话完成之前创建,因为它无法从队列中获取消息)
我的期望是正确的吗?可能出了什么问题?