mongodb/node.js 中单文档并发读写操作的问题

2024-05-25

编辑 6/15我尝试运行相同的代码,在调用之前添加延迟$doSafePush()再次收到 ConcurrencyDBError 时(即执行return when.resolve("wait").delay(35).then(function() {$doSafePush(err.object, "set", value, retries-1);});代替return $doSafePush(err.object, "set", value, retries-1);)。只要我等待至少 35 毫秒,它就可以正常工作;低于该阈值它可以工作有时。感觉像是一个神奇的数字,但它正在起作用......

如果有人有任何线索,仍然有兴趣了解为什么:)


在 Node.js 下对 MongoDB 中的单个文档进行并发读写操作时遇到问题

请参阅下面我正在运行的代码。 基本上我将一个 Collection 定义为 Mongodb 结构{_id: ObjectID, __occ: Number, set: Array}。由于我有多个事务要“并行”执行,因此当我仅在正在使用的版本具有正确的 _id 和正确的 __occ 时才更新文档时,我想使用经典的乐观一致性控制框架编写安全推送;否则我强制重新加载并重试。

本质上,它会导致在同一个文档上同时运行多个写入和读取(如果写入失败)操作。

不幸的是,我无法让它工作。在某些时候,Mongo 开始返回有趣的文档,这让一切都变得混乱。

从下面运行代码,我有以下输出(对应于下面最后一个函数最底部的 debug(...) 命令)

第 1 部分:工作正常

29033b successfully added >>> occ=1 set={#1 elts, ["29033b"]} +87ms
29033c successfully added >>> occ=2 set={#2 elts, ["29033b","29033c"]} +33ms
29033d successfully added >>> occ=3 set={#3 elts, ["29033b","29033c","29033d"]} +37ms

第 2 部分:第一次事故:前第 3 项被另一个项替换 => 第一个数据丢失

290342 successfully added >>> occ=3 set={#3 elts, ["29033b","29033c",**"290342"**]} +37ms

第 3 部分:第二次事故;回到原来的项目 #3 => '290342' 丢失

29033e successfully added >>> occ=4 set={#4 elts, ["29033b","29033c",**"29033d"**,"29033e"]} +32ms
290344 successfully added >>> occ=5 set={#5 elts, ["29033b","29033c","29033d","29033e","290344"]} +10ms
290343 successfully added >>> occ=6 set={#6 elts, ["29033b","29033c","29033d","29033e","290344","290343"]} +35ms

第 4 部分:第三次事故;我们回到第三位的项目“290342”;它变得丑陋了

29033f successfully added >>> occ=4 set={#4 elts, ["29033b","29033c",**"290342"**,"29033f"]} +31ms

第5部分:第四次事故;再次,项目 #3 发生了变化,并且第 3 部分中的项目 #4 丢失了

290340 successfully added >>> occ=5 set={#5 elts, ["29033b","29033c","29033d",**"29033e"**,**"290340"**]} +35ms

第 6 部分:第五次事故;第 4 项已更改

290341 successfully added >>> occ=5 set={#5 elts, ["29033b","29033c","29033d","29033e",**"290341"**]} +45ms

这是我在 MongoDB 中的内容(通过 mongo shell 查询)

{ "_id" : ObjectId("575f8981762120ce1a290324"), "__occ" : 5, "set" : [ "29033b", "29033c", "29033d", "29033e", "290340" ] }

我原以为 findOneAndUpdate 是原子的,但它的行为对我来说很奇怪。任何人都可以帮助我找出我做错了什么

提前致谢

PS:为了便于阅读,所有数字都被缩短,但它们实际上是正确的 MongoDB ID,例如575f8981762120ce1a29033b => 29033b

// ------ MAIN CODE ------
var document = 'a previously loaded document from MongoDB'; // has _id and __occ properties
var valueList = [
    "29033b",
    "29033c",
    "29033d",
    "29033e",
    "29033f",
    "290340",
    "290341",
    "290342",
    "290343",
    "290344"
];

var promiseArray = [];
for (let i = 0; i < valueList.length; i++) {
    promiseArray.push(safePush(document, valueList[i]));
}

return when.all(promiseArray)
.then(function(array) {
    // do something with results
})

// ------ FUNCTIONS USED ------
function safePush(obj, value) {
    return $doSafePush(obj, "set", value)
    .then(function(updatedObject) {
        return updatedObject;
    }).catch(function(err) {
        if (err instanceof ConcurrencyDBError) {
            if (retries > 0) {
                return $doSafePush(err.object, "set", value, retries-1);
            } else {
                err.message += " => max number of retries reached, failing";
            } 
        }
        // else
        var message = err.message || "ERROR Unexpected error";
        return when.reject(GenericError.create(message, err));
    });
}

function $doSafePush(obj, property, value) {
    var $query = {
        '_id': obj.id,
        '__occ': obj.__occ
    }
    var $update = {
        "$push": {}
        "$inc": {
            "__occ": 1
        }
    };
    $update["$push"][property] = value; // Update == $push value into 'property' array and $inc __occ counter

    return $getMongoCollection("Users").findOneAndUpdate($query, $update, {returnOriginal: false})
    .then(function(r) {
        var result = r.value;

        if (result == null) {
            // No object matching $query found => OCC error
            // Load new object and reject Promise
            return $getMongoCollection().findOne({_id: new ObjectID(obj._id)})
            .then(function(newObj) {
                return when.reject(new ConcurrencyDBError(util.format("ERROR Concurrency error trying to add %s to %s", value, property), newObj));
            });
        }
        // Else Object was found and updated => return it
        debug("BGCHECK 3 >>> OK >>> %s successfully added >>> occ=%d set={#%d elts, %j}", value, result.__occ, u.getProperty(result, property).length, u.getProperty(result, property));
        return when.resolve(result);
    });
}

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mongodb/node.js 中单文档并发读写操作的问题 的相关文章

  • Mongodb更新很多

    我正在使用express js 和 npm 模块 mongodb 进行开发 并以 mongodb 作为数据库 我有两个集合 即 用户 和 活动 一个用户可能有数千个活动 首先 我将用户的 id 姓名和图片 url 存储到 关系的活动文件 请
  • MongoDB自增ID

    MongodB 中自动生成的 ID 的大小为12 Bytes大整数的大小是8 bytes 我在 4 台运行 Ubuntu Server 的机器上有一个 mongodb 集群 但我现在只是在测试 插入只能通过一台服务器 即 Nodejs 服务
  • PHP 中的 MongoDB - 如何将项目插入集合中的数组中?

    这必须很容易 但我似乎无法弄清楚 假设我有一个集合users这是集合中的第一项 id ObjectId 4d8653c027d02a6437bc89ca name Oscar Godson email email protected cdn
  • 为 Meteor 数据创建编号列表

    有没有办法获取 Meteor 集合中项目的编号列表的 编号 我知道我可以在 html 中做到这一点 但我觉得如果我可以在 spacebars 中放置一些东西 那么样式会更容易 如果我可以使用更好的术语 请告诉我 像这样的东西 前 20 部电
  • Mongodump之后,调用MongoRestore挂起

    我们正在尝试在相对较小的数据库上做一个简单的 MongoDump 我们的步骤很简单 export 从目标机器上删除现有数据库 在目标机器上导入 MongoDump 完美执行 mongodump out root mongo prod DB
  • Mongodb - 为现有集合添加架构

    我的 MongoDB 中有一个包含 1300 万条记录的集合 不幸的是 当我创建这个集合时 没有为其创建模式 我想知道除了备份整个数据库 创建架构并上传所有数据之外 是否有任何方法可以添加 JSON 架构 您可以使用以下方法将 JSON 架
  • nodejs (libuv) 事件循环是否在一个阶段(队列)中执行所有回调,然后再进入下一阶段或以循环方式运行?

    我正在研究 Node js 中 libuv 提供的事件循环 我遇到了关注 Deepal Jayasekara 的博客 https blog insiderattack net event loop and the big picture n
  • 为 Node.js 客户端应用程序保留 Firebase 用户

    我正在使用 Firebase 构建 Node js 命令行界面 CLI 用于与后端进行身份验证 我想避免让用户每次运行命令时都输入密码 相反 我想实现一个 登录 流程 将凭证保留到文件系统 该凭证可用于后续的无密码身份验证 直到用户 注销
  • 带有 npm 启动脚本的 Nodejs 应用程序

    我对nodejs很陌生 在我的docker化环境中 我想为nodejs应用程序提供appdynamics支持 这要求每个应用程序都要求将以下内容作为其应用程序的第一行 require appdynamics profile controll
  • 如何将函数设置为 multer 上的限制参数?

    在这个问题之后 我可以使用 multer 和单个 html 表单上传不同文件夹中的多个文件吗 https stackoverflow com questions 39726862 cani upload many files in diff
  • 如何在 VSCode 调试器中执行异步函数? [复制]

    这个问题在这里已经有答案了 如果我在一些 javascript 代码中放入 VSCode 调试器并使用 wait 调用异步函数 它只会返回一个承诺 如何解决调试器中的承诺 以便我可以看到结果是什么 例如 如果我定义一个像这样的函数 cons
  • Apache + Symfony2 + HTTPS + Node.js + Socket.io:socket.emit 未触发

    我花了几个小时来解决这个问题 但毫无结果 编辑 找到解决方案 参见我的答案 项目背景 我正在构建一个项目Symfony2 这需要一个用于上传大文件的模块 我选择了Node js and Socket IO 我必须从头开始学习 所以我可能会错
  • Mongoose.js instance.save() 回调未触发

    var mongo require mongoose var connection mongo createConnection mongodb 127 0 0 1 test connection on error function err
  • 将域类从 GORM 独立模块导入到 Grails 中

    我有两块拼图 1 一个名为的无 Grails 项目core module使用独立的 GORM dependencies compile org grails grails datastore gorm mongodb 6 0 4 RELEA
  • 无法在适当的时间对域调用 dispose

    我有一个问题domain模块 目前 我正在尝试捕获请求中引发的任何未捕获的错误 使用express中间件和域 所有请求在调用之前都会通过此函数路由next并继续走正确的路线 app use req res next gt domain cr
  • 从自己的 gitlab 服务器安装节点模块

    我想从我们的 gitlab 服务器安装节点模块 这是存储库的链接 http ABCD GITLAB myGroup myNodeModule git http ABCD GITLAB myGroup myNodeModule git 根据n
  • nvm 与 npm 配置“前缀”选项不兼容:

    我正在尝试运行另一个 NodeJS 版本nvm但出现此错误 nvm use v4 2 4 nvm is not compatible with the npm config prefix option currently set to Us
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 使用 PHP 从 Mongo 解码 JSON

    我已经看过这个线程 PHP 解码嵌套 JSON https stackoverflow com questions 3555335 php decode nested json并没有设法用它来解决我的问题 我目前正在从 Mongo 获取 J
  • 在 MySQL 中存储表情符号的编码问题:如何使用 Prisma ORM 在 NodeJS 中定义字符排序规则?

    亲爱的 Nodejs 专家和数据库专家 我们在 MySQL 数据库中存储表情符号和其他特殊字符时遇到问题 我们使用 Prisma 得到一个错误 这是我们使用的 ORM 参数无法从排序规则 utf8 general ci 转换为 utf8mb

随机推荐

  • 仅最后一个用户控件显示内容控件

    我有一个奇怪的问题 我创建了一个带有标签和画布的用户控件 画布引用资源 但画布仅显示在我的堆栈面板中的最后一个控件上 这是我的窗户
  • 为什么 useState 会导致组件在每次更新时渲染两次?

    我这里有一段简单的代码 import React useState from react import styles css export default function App const number setNumber useSta
  • 参考指南:这个符号在PHP中是什么意思? (PHP 语法)

    这是什么 这是关于 PHP 语法时不时出现的问题的集合 这也是一个社区 Wiki 因此邀请每个人参与维护此列表 为什么是这样 过去很难找到有关运算符和其他语法标记的问题 主要思想是提供 Stack Overflow 上现有问题的链接 这样我
  • Qt 创建者 4.8.4。 Windows 7 - 64 位安装

    我在 QT 方面遇到了一些困难 我需要在学校使用它来完成一些 GUI 应用程序 我最近完成了以下步骤 1 mingw get inst 20120426 exefrom 来源锻造 http sourceforge net projects
  • WHERE 子句中的可选参数[重复]

    这个问题在这里已经有答案了 假设有一个具有 3 个参数的存储过程 在所有可能性中 我希望通过一个单一的方法来实现这一目标WHERE子句不会失去对 using 的控制 AND OR 太多了 Example Params CITY VARCHA
  • 如何匹配撇号('),除非它被转义(\')?

    是否可以为此构造一个正则表达式 如果是这样 如果有人展示如何操作 我将不胜感激 使用这个正则表达式
  • 用户界面上的“ID”或“Id”

    我工作的 QA 经理刚刚告诉我 我的桌面应用程序存在一个错误 因为登录提示应该是 操作员 ID 而却是 操作员 ID 她的论点是 本我 指的是弗洛伊德 精神装置 的自我部分 在语义上是不正确的 现在 作为一名肛门工程师 AE 我当然必须去查
  • 我如何加入 Eloquent:关系?

    我的查询是这样的
  • Paypal一键购买

    是否可以使用Paypal API实现一键购买 或 Paypal 自适应 API 而不是每次都要求用户登录 提前致谢 Johnny 要获得 Paypal 的 一键结账 体验 解决方案是 预先批准的付款流程 下图显示了一个过程中的基本控制流程前
  • Jquery 对话框部分视图服务器端验证“保存”按钮单击

    我有一个显示数据的表格 表格的每一行都有编辑按钮 单击编辑按钮时 将出现一个 jquery 对话框 其中包含用于编辑用户信息的表单以及保存和取消按钮 表单只不过是部分视图 按钮是部分视图的一部分
  • 将数据从 Kafka 存储传输到 Kafka 主题

    我想在卡夫卡做这样的事情 继续将数据存储在 KStream Ktable Kafka store 中 当我的应用程序收到特定事件 数据时 仅将上述存储中的特定数据集发送到主题 我们可以在卡夫卡中做到这一点吗 我认为单独使用 Kafka 消费
  • Java 8 Nashorn:控制台几乎无法使用

    我在 OSX 10 9 2 上使用 Java 8 build 1 8 0 b132 我正在使用 Java 8 中的新 JavaScript 运行时 Nashorn 我在用Library Java JavaVirtualMachines jd
  • 如何从 mysqldump 中删除表

    如何删除 mysqldump 中包含大量表的一个大表的输出 我有一个 6 GB 大的数据库转储 但其中 90 只是一个日志记录表 cache entries 我的备份中不再需要它 如何轻松删除转储中描述大型日志记录表的部分 我找到了这个 h
  • 当键位于父类中时,如何将一对多集合映射到连接的子类

    我想将一对多集合映射到子类 但集合的键是父类的属性 目前我正在映射 AbstractFoo Foo 和 Bar 类 如下所示
  • 检测 IMG 元素何时在 Angular 2+ 中加载

    我在用Angular 2我需要检测图像是否已加载到图像标签中 有这样的活动吗 像这样的东西 img img
  • 将 .NET 类库(主要定义 CRUD 操作)公开为服务

    公开现有内容的最佳 有效和最快的方法是什么 类 图书馆 主要定义 CRUD 操作 作为service 周转基金服务 or WCF数据服务 以便它可以与银光 or Ajax 在那儿tools 代码生成器 RAD 工具 哪些可以支持这个 预先感
  • 如何使用授权 API 设置部分身份验证

    好的 我正在通过 Authorize net API 设置部分付款 以便能够使用多张卡支付单笔余额 费用 我假设他们的部分身份验证功能涵盖了我的用例 但在测试中 我可以在此处使用 API 实时控制台向您展示一个问题 https develo
  • CSS:100% 宽度和背景?

    在我的页面中 有 2 3 个部分的宽度和背景为 100 当我全屏打开它时 一切正常 但当屏幕小于 960px 本节内容的宽度 时 背景图像不是整个页面 右侧的瞬间隐藏在没有背景的地方 它是白色的 你可以在这里明白我的意思 http mico
  • 如何将SSRS共享数据集和数据源直接导入BIDS 2008?

    Using SSRS 报表服务器 10 50 1600 1 BIDS Visual Studio 9 0 30729 4462 来自同一域和网络上的远程客户端 不在 SSRS 服务器上本地 我希望能够将报表服务器上的现有共享数据源和共享数据
  • mongodb/node.js 中单文档并发读写操作的问题

    编辑 6 15我尝试运行相同的代码 在调用之前添加延迟 doSafePush 再次收到 ConcurrencyDBError 时 即执行return when resolve wait delay 35 then function doSa