【问题标题】:Mongodb v4.0 Transaction, MongoError: Transaction numbers are only allowed on a replica set member or mongosMongodb v4.0 Transaction, MongoError: Transaction numbers are allowed on a replica set member or mongos
【发布时间】:2018-12-29 21:52:43
【问题描述】:

我已经在 Nodejs 中安装了 MongoDB v4.0 最令人惊叹的功能 Transaction,并以 mongodb 3.1 作为驱动程序。

当我尝试使用事务会话时,我遇到了这个错误:

MongoError:事务号仅允许在副本集成员或 mongos 上。

那是什么,我怎样才能摆脱它?

感谢任何建议。

【问题讨论】:

  • 您可以使用 MongoDB atlas 解决此问题

标签: javascript node.js mongodb transactions


【解决方案1】:

Transactions 无疑是MongoDB 4.0 中最令人兴奋的新功能。但不幸的是,大多数安装和运行 MongoDB 的工具都会启动独立服务器,而不是副本集。如果您尝试在独立服务器上启动会话,则会收到此错误。

为了使用事务,您需要一个 MongoDB 副本集,并且在本地启动副本集进行开发是一个复杂的过程。新的run-rs npm module 使启动副本集变得容易。运行 run-rs 即可启动副本集,run-rs 甚至会为您安装正确版本的 MongoDB。

Run-rs 除了 Node.js 和 npm 之外没有任何外部依赖。您无需安装 Docker、自制软件、APT、Python 甚至 MongoDB。

使用npm's -g 标志全局安装run-rs。您还可以在 package.json 文件的 devDependencies 中列出 run-rs。

npm install run-rs -g

接下来,使用 --version 标志运行 run-rs。 Run-rs 将为您下载 MongoDB v4.0.0。别担心,它不会覆盖您现有的 MongoDB 安装。

run-rs -v 4.0.0 --shell

然后在您的连接字符串中使用 replicaSet=rs

你可以找到更多关于它的细节here

【讨论】:

  • bitnami/mongodb docker 镜像也很有用,它允许您使用 docker-compose 设置副本集:github.com/bitnami/…
  • 从文档看来,使用副本集运行现有的(或新的)mongod 实例相当简单:docs.mongodb.com/manual/tutorial/…
  • 知道为什么使用事务的能力需要 MongoDB 副本集吗? (在我的情况下,我有在 docker 上运行的 MongoDb 实例进行测试,并且由于这个限制而无法运行事务)
  • 也遇到了同样的限制。尝试使用 mongodb-memory-server 但我想我只是不太了解副本集。
  • 知道为什么它需要全局安装,而不仅仅是作为开发依赖项吗?
【解决方案2】:

我最近遇到了同样的问题。就我而言,这是因为我连接到的远程 Mongo 服务器的版本与我的本地开发环境不同。

为了快速解决问题,我在连接字符串中添加了以下参数:

?retryWrites=false

【讨论】:

    【解决方案3】:

    使用 docker

    进行本地开发的可能解决方案

    创建 Dockerfile

    FROM mongo:4.4.7
    RUN echo "rs.initiate();" > /docker-entrypoint-initdb.d/replica-init.js
    CMD [ "--replSet", "rs" ]
    

    构建这个 Dockerfile

    docker build ./ -t mongodb:4.7-replset
    

    运行这个创建的图像

    docker run --name mongodb-replset -p 27017:27017 -d mongodb:4.7-replset
    

    使用这个 URI 连接到数据库

    mongodb://localhost:27017/myDB
    

    【讨论】:

    • 建议的解决方案不适用于 MongoDB 5.0.5,因为“MongoServerError:命令 replSetInitiate 需要身份验证”(docker-entrypoint.sh 不会使用用户名和密码调用 mongo,它也不会打印错误,只有将mongo替换为mongosh才能看到)。除此之外,您还需要CMD ["--replSet", "rs", "--keyFile", "/etc/mongodb.key"]
    • 即使在RUN echo 'rs.initiate();' > /docker-entrypoint-initdb.d/replica-init.script RUN echo 'mongosh -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" < /docker-entrypoint-initdb.d/replica-init.script' > /docker-entrypoint-initdb.d/replica-init.sh 周围进行这项工作,我们也会得到MongoServerError: This node was not started with the replSet option。这仅仅是因为docker-entrypoint.sh 不是为运行副本而设计的。实际上,看起来它的设计目的是不运行它们。源码见# remove "--auth" and "--replSet" for our initial startup
    • 这里是相关的重大更改:github.com/docker-library/mongo/issues/…
    • 如果有人感兴趣,请参阅github.com/thenewboston-developers/Node/pull/69 中的脚本/docker-entrypoint.sh.patch 和 Dockerfile 以了解解决方法/解决方案
    • 它对我有用,谢谢!!
    【解决方案4】:

    我得到了解决方案,它只是 MongoDB 配置文件中的三行配置。

    从 MongoDB atlas 切换并在我的 CentOS 7 VPS 上使用 WHM 安装 MongoDB v 4.4.0 后,我也遇到了这个问题。

    run-rs 解决方案对我不起作用,但我设法在没有任何第三方工具的情况下解决了这个问题,遵循以下步骤:

    1。关闭mongod

    最有效的方法是使用命令mongo 进入MongoDB shell 检查方法

    db.shutdownServer()
    

    您将无法使用 MongoDB 服务器。 对我来说,关闭过程耗时太长,然后我用命令杀死了该进程:

    systemctl stop -f mongod
    

    如果你杀死了mongod 进程,你可能需要运行 mongod --dbpath /var/db --repair

    var/db 应该指向您的数据库目录。

    2。设置副本集配置。

    对于replicaSet 设置步骤,请查看/etc/mongod.conf 文件, 查找 replication 值行,您应该添加以下行,如下所示:

    replication:
       oplogSizeMB: <int>
       replSetName: <string>
       enableMajorityReadConcern: <boolean>
    

    在下一步使用replSetName 值。

    这些设置的示例:

       oplogSizeMB: 2000
       replSetName: rs0
       enableMajorityReadConcern: false
    

    3。添加您的连接字符串 URL。

    将 replSetName 的值添加到您的连接 URL &amp;replicaSet=--YourReplicationSetName--

    如果您使用了我们示例中的名称 rs0,那么您应该将 replicaSet=rs0 添加到您的数据库连接 URL 查询中

    4。再次打开 mongod

    输入命令:systemctl start mongod

    5。访问您的副本集数据库

    使用命令mongo进入MongoDB shell,输入命令rs.initiate() 现在您应该在您的副本集数据库中。

    【讨论】:

    • 我认为本地开发的最佳解决方案。无需任何第三方软件即可轻松完成。
    • 我们需要为 replSetName 赋予什么值?你能举个例子吗
    • 嗨@KannanT,我修改了我的答案并附上了一个例子。
    【解决方案5】:

    为了使用事务,你需要一个 MongoDB 副本集,并且在本地启动一个副本集进行开发是一个涉及的过程。

    您可以使用run-rs npm module。零配置 MongoDB 运行器。启动一个没有非节点依赖的副本集,甚至没有 MongoDB。

    或者您可以简单地在MongoDB Atlas 中创建一个帐户,它为您提供有限资源的 MongoDB 集群,因此您可以运行/测试您的应用程序。

    MongoDB Atlas

    【讨论】:

      【解决方案6】:

      我已经与这个问题作斗争好几个星期了。我让你我的结论。 为了能够在分片集群上使用事务,您需要在集群上至少运行 MongoDB 4.2。如果集群没有分片,从 4.0. 我正在使用一个作为子依赖项 mongodb NodeJS 驱动程序的库。版本 3.3.x 的此驱动程序在版本 4.0.4 的分片 MongoDB 集群上失败。 我的解决方案是将集群更新到 4.2 版本。

      源代码:https://www.bmc.com/blogs/mongodb-transactions/

      【讨论】:

        【解决方案7】:

        适用于mongo:5.0.5-focal 图像。

        Dockerfile:

        FROM mongo:5.0.5-focal AS rs-mongo
        
        # Make MongoDB a replica set to support transactions. Based on https://stackoverflow.com/a/68621185/1952977
        RUN apt-get update && apt-get install patch
        
        # How to create scripts/docker-entrypoint.sh.patch
        # 1. Download the original file:
        #    wget https://github.com/docker-library/mongo/raw/master/5.0/docker-entrypoint.sh
        #    ( wget https://github.com/docker-library/mongo/raw/b5c0cd58cb5626fee4d963ce05ba4d9026deb265/5.0/docker-entrypoint.sh )
        # 2. Make a copy of it:
        #    cp docker-entrypoint.sh docker-entrypoint-patched.sh
        # 3. Add required modifications to docker-entrypoint-patched.sh
        # 4. Create patch:
        #    diff -u docker-entrypoint.sh docker-entrypoint-patched.sh > scripts/docker-entrypoint.sh.patch
        # 5. Clean up:
        #    rm docker-entrypoint.sh docker-entrypoint-patched.sh
        COPY scripts/docker-entrypoint.sh.patch .
        RUN patch /usr/local/bin/docker-entrypoint.sh docker-entrypoint.sh.patch
        RUN mkdir -p /etc/mongo-key && chown mongodb:mongodb /etc/mongo-key
        
        CMD ["--replSet", "rs", "--keyFile", "/etc/mongo-key/mongodb.key"]
        

        脚本/docker-entrypoint.sh.patch:

        --- docker-entrypoint.sh    2022-01-04 15:35:19.594435819 +0300
        +++ docker-entrypoint-patched.sh    2022-01-06 10:16:26.285394681 +0300
        @@ -288,6 +288,10 @@
            fi
        
            if [ -n "$shouldPerformInitdb" ]; then
        +
        +     openssl rand -base64 756 > /etc/mongo-key/mongodb.key
        +    chmod 400 /etc/mongo-key/mongodb.key
        +
                mongodHackedArgs=( "$@" )
                if _parse_config "$@"; then
                    _mongod_hack_ensure_arg_val --config "$tempConfigFile" "${mongodHackedArgs[@]}"
        @@ -408,7 +412,14 @@
                set -- "$@" --bind_ip_all
            fi
        
        -   unset "${!MONGO_INITDB_@}"
        +  echo 'Initiating replica set'
        +  "$@" --logpath "/proc/$$/fd/1" --fork
        +  echo 'rs.initiate({"_id":"rs","members":[{"_id":0,"host":"127.0.0.1:27017"}]});' | mongosh -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD"
        +  "$@" --logpath "/proc/$$/fd/1" --shutdown
        +  echo 'Done initiating replica set'
        +
        +  unset "${!MONGO_INITDB_@}"
        +
         fi
        
         rm -f "$jsonConfigFile" "$tempConfigFile"
        

        docker-compose.yml:

        version: '3.9'
        
        services:
          mongo:
            image: rs-mongo:current
            restart: always
            env_file:
              - .env
            ports:
              - 127.0.0.1:27017:27017
            volumes:
              - mongo-db:/data/db
              - mongo-configdb:/data/configdb
              - mongo-key:/etc/mongo-key
        
        volumes:
          mongo-db:
            driver: local
          mongo-configdb:
            driver: local
          mongo-key:
            driver: local
        

        更新日期: 2022 年 1 月 6 日

        【讨论】:

          猜你喜欢
          • 2019-09-16
          • 2013-04-03
          • 2014-07-29
          • 1970-01-01
          • 2015-06-19
          • 1970-01-01
          • 2021-11-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多