可靠队列的快照隔离已断开

本文关键字:隔离 断开 快照 队列 | 更新日期: 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,应该看到不受其他事务影响的一致快照。只有拥有快照的事务所做的更改才是可见的。

对于可靠的字典确实是这样,但对于可靠的队列却不是这样。

为可靠队列拍摄的快照(通过执行GetCountAsyncCreateEnumerableAsync)确实不受其他事务所做的修改的影响,但前提是我们自己不做任何更改。这样做不仅会使我们自己的更改在快照中可见,而且还会暴露来自其他事务的更改。

下面的代码片段可以放到一个可靠的服务中来重现:

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。我们会尽快修好的。给您带来的不便,我深表歉意。

问题解决后,我将更新此线程。