MongoDB Change Events 可以被认为是独一无二的吗?

问题描述

说明

我正在利用 MongoDb 更改流(C# MongoDB.Driver v2.12.0)来跟踪单个集合的更改。 在实验用例中,集合存储有关线程执行的信息。

一个线程有两个属性

  • Status - 正在运行、已阻止或已完成
  • BlockedCount - 阻塞线程数

在执行期间,线程可以产生子线程并被阻塞,直到所有子线程都没有完成。每当子线程完成其执行时,它都会通过递减父线程的 BlockedCount 来更新数据库。一旦 BlockedCount 降至 0,父线程应继续执行。

订阅变更流的代码

var pipeline = new EmptyPipelineDeFinition<ChangeStreamDocument<T>>()
                    .Match(change => change.OperationType == ChangeStreamOperationType.Insert ||
                                     change.OperationType == ChangeStreamOperationType.Update ||
                                     change.OperationType == ChangeStreamOperationType.Replace)
                    .AppendStage<ChangeStreamDocument<T>,ChangeStreamDocument<T>,ChangeStreamOutputWrapper<T>>(
                                     "{ $project: { '_id': 1,'fullDocument': 1,'ns': 1,'documentKey': 1 }}");

var options = new ChangeStreamOptions
{
    FullDocument = ChangeStreamFullDocumentOption.UpdateLookup
};

using (var cursor = await coll.WatchAsync(pipeline,options,cancellationToken))
{
    await cursor.ForEachAsync(async change =>
    {
        // await some handler routine
    },cancellationToken);
}

问题

我注意到的是,即使更新操作完全相同,更改事件也可能不同。 为了更好地解释这一点,这里有一个例子:

有 1 个父线程和 3 个子线程完成它们的执行,观察到两种不同的行为:

  • 父线程的 3 个不同的更新事件:

    • “状态”:“阻塞”,“阻塞计数”:2
    • “状态”:“阻塞”,“阻塞计数”:1
    • “状态”:“阻塞”,“阻塞计数”:0
  • 父线程的 3 个相同的更新事件:

    • “状态”:“阻塞”,“阻塞计数”:0
    • “状态”:“阻塞”,“阻塞计数”:0
    • “状态”:“阻塞”,“阻塞计数”:0

问题

  1. 这是否被视为正常行为?
  2. 是否有某种配置可以防止这种情况发生,并且仅触发“最新”更新?

解决方法

是的,这是预期的行为。文档 (link) 指出:

fullDocument 文档表示更新文档的最新多数提交版本。 fullDocument 文档可能与更新操作时的文档不同,具体取决于更新操作和文档查找之间发生的交错多数提交操作的数量。

据我所知,没有办法克服或调整这种行为。但是,您可以做的是直接读取updateDescription,手动跟踪更改。如果 BlockedCount 只是被设置(即,不删除并稍后重新添加),它不会很复杂。