可靠队列的快照隔离已断开
本文关键字:隔离 断开 快照 队列 | 更新日期: 2023-09-27 18:17:21
UPDATE:此错误已于2017年2月3日在Service Fabric SDK版本2.4.164中修复。引用自发行说明:
修复ReliableQueue正确处理额外的事务级别和组合
修复了ReliableQueue。如果GetCountAsync也在做Read Your Own Write,则它不坚持快照隔离。这个问题最初是在Stack Overflow上报道的。感谢您的bug报告。
我正在为Service Fabric可靠集合编写模拟。我需要这些模拟尽可能接近地模拟实际实现的事务行为。
因此,我编写了几个测试用例,我运行它们来验证我的模拟的行为是否像实际实现一样。
然而,在处理快照隔离的一些测试用例中,我发现我的模拟有不同的行为。但仔细一看,我不太确定是我的错。
所以我想我可能偶然发现了一个bug,关于队列强制快照隔离的可靠性。
用于快照隔离的MSDN文档说:
事务只能识别在事务开始之前提交的数据修改。在当前事务开始之后,其他事务所做的数据修改对于当前事务中执行的语句是不可见的。
:
可靠队列支持Read Your Writes。换句话说,事务中的任何写操作对于属于同一事务的后续读操作都是可见的。
因此,强制快照隔离的操作,如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!
}
我需要知道这是设计的,文档是不正确的,还是这是一个bug。或者如果我误解了什么。
感谢您报告这个问题。这是可靠队列中的一个bug。我们会尽快修好的。给您带来的不便,我深表歉意。
问题解决后,我将更新此线程。