C# Driver SafeMode off Upserts - 并非所有记录都已更新/插入

标签 c# mongodb

在我们的应用程序中,我们正在进行大量插入/更新(从 1k 到 100k 不等),我注意到并非所有记录都被保存。它可以在关闭安全模式的情况下保存 90%-95% 的记录。

使用安全模式执行更新插入可以成功更新所有记录,但速度太慢。我记得在某处读到,即使关闭安全模式,除非服务器不可用,否则更新/插入应该没有理由失败。

我写了一个小应用程序来测试这个,并包含了下面的代码。它尝试将 100,000 个整数插入 Mongo,在运行后检查时,我在集合中看到大约 90,000 条记录。

(注意:我正在使用并行更新,因为我是通过_id 更新的,Mongo 2.0 在使用_id 时支持并行操作。当不使用 Parallel.Foreach 时,我仍然会看到一些记录丢失,尽管不是那么大)

        MongoServer server = MongoServer.Create(host);

        MongoDatabase test = server.GetDatabase("testDB");

        var list = Enumerable.Range(0, 100000).ToList();

        using (server.RequestStart(test))
        {
            MongoCollection coll = test.GetCollection("testCollection");

            Parallel.ForEach(list, i =>
            {
                var query = new QueryDocument("_id", i);
                coll.Update(query, Update.Set("value",100), 
                             UpdateFlags.Upsert, SafeMode.False);;
            });
        }

所以我想我的问题是:以 100% 的成功率快速进行大量更新的最佳方法是什么?

我不能使用 insert,因为我有许多进程写入 Mongo,并且无法确定某个文档是否存在,这就是我使用 Upsert 的原因。

最佳答案

当您使用 SafeMode.False 时,C# 驱动程序只会将插入/更新消息写入套接字,而不会等待回复。当您非常快速地向套接字写入大量数据时,它会在客户端得到缓冲,网络堆栈将尽可能快地将字节喷射到网络上。如果您使网络饱和,则可以备份很多东西。

我的猜测是,在网络堆栈有机会将所有剩余字节写入网络之前,您正在退出进程。这可以解释丢失的文件。

最好的办法是在最后调用 Count,不是一次,而是重复调用,直到计数等于您认为应该的值。那时您知道没有数据要传输。

但是,如果任何插入由于任何原因(例如,违反唯一索引)而失败,则计数永远不会达到您的预期值。在不使用 SafeMode.True 的情况下,无法 100% 知道插入/更新是否有效。

请注意,大多数长期存在的服务器进程永远不会出现此问题,因为它们永远不会退出。

关于C# Driver SafeMode off Upserts - 并非所有记录都已更新/插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7779433/

相关文章:

node.js - 在单个查询中从 Mongo DB 中删除最新文档

c# - 如何在 Xamarin 的本地通知中显示应用名称?

c# - 使用 C# 从 SQL 显示和保存 "time"数据类型?

mongodb - 维护的Dart ORM(特别适用于mongodb)

java - 为 Spring Data 运行的每个查询设置注释

javascript - $in 用于多个值

node.js - 唯一和稀疏模式级索引 MongoDB 和 Mongoose

c# - 如何防止将 Item 添加到 DataGrid?

c# - 实现一个MySQL命令进度条

c# - 回发时输入为空