更新:2017年2月3日Service Fabric SDK version 2.4.164修正了此错误。引用来自release notes:
修复ReliableQueue以正确处理其他交易级别和组合
修复了ReliableQueue.GetCountAsync如果还执行Read Your Own Write而不遵守快照隔离的错误。此问题最初在Stack Overflow上报告。感谢您的错误报告。
我正在为Service Fabric可靠集合编写模拟。我需要这些模拟尽可能接近地模仿真实实现的事务行为。
因此,我编写了几个测试用例,用于验证我的模拟行为与实际实现类似。
但是,在一些处理快照隔离的测试用例中,我发现我的模拟具有不同的行为。但仔细观察后,我并不确定故障是否在我身边。
所以我认为我可能偶然发现了一个可靠的队列强制快照隔离的错误。
快照隔离的MSDN docs表示:
事务只能识别在事务开始之前提交的数据修改。在当前事务开始后由其他事务进行的数据修改对当前事务中执行的语句不可见。
和
可靠的队列支持阅读您的写作。换句话说,事务中的任何写入对于属于同一事务的后续读取都是可见的。
因此,强制快照隔离的操作(如GetCountAsync
)应该会看到一个不受其他事务影响的一致快照。只有拥有快照的交易所做的更改才能显示。
对于可靠的词典确实如此,但对于可靠的队列则不然。
为可靠队列拍摄的快照(通过执行GetCountAsync
或CreateEnumerableAsync
)确实不受其他交易所做的修改的影响,但前提是我们自己不进行任何更改。这样做不仅会使我们自己的更改在快照中可见,还会显示其他事务的更改。
以下代码段可以放入可靠的服务中以重现:
public async Task Verify_that_reliable_queue_snapshot_isolation_is_broken()
{
// Get an empty reliable queue
var name = Guid.NewGuid().ToString();
var queue = await this.StateManager.GetOrAddAsync<IReliableQueue<string>>(name);
// Start transaction and take a snapshot by getting queue count
var t1 = this.StateManager.CreateTransaction();
Assert.AreEqual(0, await queue.GetCountAsync(t1)); // ok
// Enqueue something in a concurrent transaction
using (var t2 = this.StateManager.CreateTransaction())
{
await queue.EnqueueAsync(t2, "something");
await t2.CommitAsync();
}
// Snapshot should still say zero
Assert.AreEqual(0, await queue.GetCountAsync(t1)); // ok
// Enqueue something else in the first transaction
await queue.EnqueueAsync(t1, "something else");
// Count should now be 1 in t1, but it's actually 2.
Assert.AreEqual(2 /* should be 1*/, await queue.GetCountAsync(t1)); // broken!
}
我需要知道这是否是设计,文档是否错误,或者这是否是一个错误。或者如果我误解了某些东西。
感谢任何反馈。
答案 0 :(得分:1)
感谢您报告此问题Marten。这是Reliable Queue中的一个错误。我们会尽快修复它。若带来不便请谅解。
当问题得到解决时,我会在这个帖子上更新。