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

jef*_*cco 4 c# mongodb

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

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

我写了一个小应用程序来测试它,并包含下面的代码.它试图在Mongo中插入100,000个int,并且在运行后检查时,我在集合中看到大约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);;
            });
        }
Run Code Online (Sandbox Code Playgroud)

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

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

Rob*_*tam 7

当您使用SafeMode.False时,C#驱动程序只是将插入/更新消息写入套接字,而不是等待回复.当您将大量数据快速写入套接字时,它将在客户端进行缓冲,并且网络堆栈将尽可能快地将字节喷出网络.如果您正在使网络饱和,那么事情可以得到很大的支持.

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

你最好的办法是最后给Count打电话,不是一次,而是一次,直到计数等于你认为应该是的数.此时你知道没有数据可以传输.

但是,如果任何插入因任何原因(例如,违反唯一索引)而失败,则计数将永远不会达到预期值.没有100%的方法可以在不使用SafeMode.True的情况下了解插入/更新是否有效.

请注意,大多数长期存在的服务器进程永远不会出现此问