MongoDB 写安全(Write Concern)

本文介绍了MongoDB的写入安全机制(WriteConcern),详细解释了应答式与非应答式写入的区别,以及如何通过设置w、j、wtimeout等参数来平衡性能与数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MongoDB Write Concern,简称MongoDB写入安全机制,是一种客户端设置,用于控制写入安全的级别。Write Concern 描述了MongoDB写入到mongod单实例,副本集,以及分片集群时何时应答给客户端。默认情况下,mongoDB文档增删改都会一直等待数据库响应(确认写入是否成功),然后才会继续执行。本文讲述了MongoDB 应答机制及相关参数。

一、MongoDB应答机制

    MongoDB应答机制就是说对于当前数据库的写入成功与否告知客户端(db.getLastError())。如下:
            mongoDB client发出写入(或更新)请求---->mongoDB Server端写入---->通知客户端已经写入OK
    主要分为2种应答机制
            应答式写入(缺省情形,安全写入,适用于数据强一致性场景)
            非应答式写入(非安全写入,适用于数据弱一致性场景)
    实现方式
            通过Write Concern来实现,客户端驱动调用db.getLastError()方法,错误返回给客户端
            如果捕获到错误,则可以通过客户端定义的逻辑尝试再次写入或记录到特定日志等

二、Write Concern用法

    { w: <value>, j: <boolean>, wtimeout: <number> }

    w : 该选项要求确认操作已经传播到指定数量的mongod实例或指定标签的mongod实例
            w可选的的值
                    <number>
                            w:1(应答式写入)
                                    要求确认操作已经传播到指定的单个mongod实例或副本集主实例(缺省为1)
                            w:0(非应答式写入)
                                    不返回任何响应,所以无法知道写入是否成功
                                    但是对于尝试向已关闭的套接字写入或者网络故障会返回异常信息
                            w:>1(用于副本集环境)
                                    该值用于设定写入节点的数目,包括主节点

            "majority"(大多数)
                    适用于集群架构,要求写入操作已经传递到绝大多数投票节点以及主节点后进行应答

            <tag set>
                    要求写入操作已经传递到指定tag标记副本集中的成员后进行应答

    j : 该选项要求确认写操作已经写入journal日志之后应答客户端(需要开启journal功能)
            则在意外重启,宕机等情形下可以通过journal来进行数据恢复
            写入journal操作必须等待直到下次提交日志时完成写入
            为降低延迟,MongoDB可以通过增加commit journal的频率来加快journal写入

    wtimeout:
            该选项指定一个时间限制,以防止写操作无限制被阻塞导致无法应答给客户端
            wtimeout的单位为ms,当w值大于1时生效,该参数即仅适用于集群环境
            当某个节点写入时超出指定wtimeout之后,mongod将返回一个错误
            在捕获到超时之前,mongod并不会撤销其他节点已成功完成的写入
            wtimeout值为0时等同于没有配置wtimeout选项,容易导致由于某个节点挂起而无法应答

    对于单实例应答的情形,是将数据写入到内存后开始应答,除非j:true,则保证掉电后不会丢失数据

三、几种不用应答模式图示说明

1、非应答式写入图示

    MongoDB不对客户端进行应答,驱动会检查套接字,网络错误等。
    mongos> db.version()
    3.2.9
    mongos> db.version()
    3.2.9
    mongos> db
    test
    mongos> db.blogs.insert({ename:"leshami",url:"http://blog.youkuaiyun.com/leshami"},{writeConcern:{w:0}})
    WriteResult({ })   //此处应答为空

    mongos> db.blogs.find({},{_id:0})
    { "ename" : "leshami", "url" : "http://blog.youkuaiyun.com/leshami" }

这里写图片描述

2、应答式写入图示

    应答式写入是默认值
    MongoDB会在收到写入操作并且确认该操作在内存中应用后进行应答,但不会确认数据是否已写入磁盘
    同时允许客户端捕捉网络、重复key等等错误

    mongos> db.blogs.insert({ename:"john",url:"http://blog.youkuaiyun.com/john"},{writeConcern:{w:1}})
    WriteResult({ "nInserted" : 1 })    //此处应答信息显示为1个文档已插入

    mongos> db.blogs.find({},{_id:0})
    { "ename" : "leshami", "url" : "http://blog.youkuaiyun.com/leshami" }
    { "ename" : "john", "url" : "http://blog.youkuaiyun.com/john" }

这里写图片描述

3、带journal应答式写入图示

    确认写操作已经写入journal日志之后应答客户端,必须允许了日志功能,才能生效。
    写入journal操作必须等待直到下次提交日志时完成写入
    提供通过journal来进行数据恢复

这里写图片描述

4、副本集应答写入图示

    对于使用副本集的场景,缺省情况下仅仅从主(首选)节点进行应答
    建议修改缺省的应答情形为特定数目或者majority来保证数据的可靠
    如下示例,w值为2,超时为5s
            db.products.insert(
               { item: "envelopes", qty : 100, type: "Clasp" },
               { writeConcern: { w: 2, wtimeout: 5000 } }
            )       
    如果不希望每次在增删改时添加writeConcern,可以通过设置settings.getLastErrorDefaults
    如下示例,
            cfg = rs.conf()
            cfg.settings = {}
            cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
            rs.reconfig(cfg)

这里写图片描述

四、小结

1、write concern用于控制写入安全的级别,可以分为应答式写入以及非应答式写入
2、write concern是一个性能和数据强一致性的权衡,应根据业务场景进行设定
3、对于强一致性场景,建议w>1或者等于majority,以及journal为true,否则w=0
4、在副本集的情形下,建议通过配置文件来修改w以及设置wtimeout,以避免由于某个节点挂起导致无法应答

DBA牛鹏社(SQL/NOSQL/LINUX)

<think>嗯,用户想了解如何在MongoDB中配置关注(Write Concern)。这属于数据库操作的高级配置,对数据安全性和性能都有重要影响。 用户可能正在开发一个对数据一致性要求较高的应用,需要根据业务场景调整入策略。从引用内容看,用户已经查阅过相关文档,但需要更具体的配置指导。 关于配置方法,可以从三个层面展开:首先是全局默认配置,适用于整个MongoDB实例;其次是集合级别配置,适合特定业务场景;最后是操作级别配置,用于临时性调整。每个层面都需要说明具体命令和参数含义。 特别要注意w参数的三种模式:0(无确认)适用于日志类数据,1(主节点确认)是默认值,majority(多数节点确认)则用于金融等高安全场景。j参数和wtimeout的配合使用也很关键。 用户可能还关心实际应用场景的差异,比如电商订单和日志采集的配置区别。需要强调配置不当的后果:过度追求安全可能导致性能下降,而过于宽松可能丢数据。 最后要提醒测试验证方法,比如通过getLastError命令检查配置效果。这些内容都需要用中文清晰表述,数学公式保持LaTeX格式。</think>在MongoDB中配置**关注 (Write Concern)** 是确保数据入可靠性的关键机制。以下是详细配置方法及场景说明: --- ### **一、配置层级与方法** 1. **全局默认配置 (mongod/mongos 启动参数)** 修改配置文件 `mongod.conf`: ```yaml setParameter: writeConcern: { w: "majority", wtimeout: 5000, j: true } ``` 重启后生效,适用于所有未显式指定关注的操作[^1]。 2. **集合级别默认配置** 创建集合时指定: ```javascript db.createCollection("orders", { writeConcern: { w: 2 } }) ``` 3. **单次操作级别配置** 在入命令中直接指定(最常用): ```javascript db.products.insertOne( { name: "Laptop", price: 1200 }, { writeConcern: { w: "majority", j: true, wtimeout: 3000 } } ) ``` --- ### **二、核心参数详解** | 参数 | 值类型 | 作用 | 示例 | |------------|--------------|----------------------------------------------------------------------|--------------------------| | **`w`** | 整数/字符串 | 定义入确认的节点数 | `1`(仅主节点)<br>`"majority"`(多数节点) | | **`j`** | 布尔值 | 是否等待数据入磁盘日志(journal) | `true`(强持久化) | | **`wtimeout`** | 毫秒数 | 等待确认的超时时间(超时不代表入失败) | `5000`(5秒) | --- ### **三、典型场景配置示例** 1. **高性能场景(日志采集)** ```javascript db.logs.insertOne({ msg: "Error 404" }, { w: 0 }) // 无确认,最快速度 ``` 2. **平衡场景(用户订单)** ```javascript db.orders.insertOne({ item: "Book" }, { w: 1, j: true }) // 主节点持久化 ``` 3. **高安全场景(金融交易)** ```javascript db.transactions.insertOne({ amount: 100 }, { w: "majority", j: true }) // 多数节点持久化 ``` --- ### **四、验证配置效果** ```javascript // 查看最后一次操作的关注结果 db.runCommand({ getLastError: 1 }) // 返回示例: // { // "n": 1, // 影响文档数 // "writeConcern": { w: "majority", j: true }, // "wtimeout": false // 未超时 // } ``` --- ### **五、注意事项** 1. **超时处理** `wtimeout` 超时仅表示未收到确认,**不意味着入失败**,需通过日志 (`mongod.log`) 进一步核查。 2. **副本集要求** 使用 `w: N`(N>1)或 `w: "majority"` 时,需部署至少3个节点的副本集[^2]。 3. **性能影响** 关注级别越高,延迟越大。在PSA架构(主节点-从节点-仲裁节点)中,避免从节点故障时使用高等级关注[^2]。 > 配置建议:根据业务对 **数据安全性** 和 **响应速度** 的需求权衡参数。关键数据建议 `w: "majority"` + `j: true`,非关键数据可用 `w: 1`[^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风智语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值