w:1、w:majority、j:true 的延迟差多少?副本不够时 w:majority 会怎样?wtimeout 的错误意味着写入失败了吗?这篇在真实的 3 节点副本集上逐个验证。
成员状态:9901=PRIMARY, 9902=SECONDARY, 9903=SECONDARY
# 集群的默认写关注(没有显式设置时)
test> db.adminCommand({getDefaultRWConcern: 1}).defaultWriteConcern
{ w: 'majority', wtimeout: 0 }
test> var h = db.hello(); ({setName: h.setName, isWritablePrimary: h.isWritablePrimary, members: h.hosts.length, majority: Math.floor(h.hosts.length / 2) + 1})
{ setName: 'rsm46', isWritablePrimary: true, members: 3, majority: 2 }一个 primary、两个 secondary,默认写关注是 w: majority。
写关注 中位数 p99 w:0 0.0 ms 0.2 ms w:1 0.2 ms 0.7 ms w:1, j:true 4.0 ms 9.0 ms w:2 0.6 ms 1.5 ms w:majority 4.0 ms 8.1 ms w:3 0.6 ms 1.3 ms w:majority, j:true 4.0 ms 8.4 ms
单条 insert:w:1 0.2 ms;w:2 / w:3 0.6 ms;j:true 与 w:majority 约 4 ms,因为要等 journal 落盘。
w:majority(只剩 2 个节点在线):成功,耗时 23.5 ms
w:3 wtimeout=1000:1016 ms 后返回 WriteConcernError code=64: waiting for replication timed out
但 w:3 那条文档已经写进了 primary:count({k: "w3"}) = 1剩 2 个节点时 w:majority 仍成功;w:3 等到 wtimeout 返回 code 64 的 WriteConcernError,但文档已经在 primary 上了——写关注错误不等于写入失败。
只剩 1 个节点在线:isWritablePrimary = False,secondary = True
向它写入:NotPrimaryError: not primary, full error: {'topologyVersion': {'processId': ObjectId('6acc4c1e275f45487358aprimary 看不到多数就降级成 secondary,继续写会得到 NotPrimaryError。
w:0 重复插入 _id:1:没有抛异常(服务端没把错误告诉客户端) w:1 重复插入 _id:1:DuplicateKeyError t5 里实际文档数 1
不要求确认,重复键等错误不会报告给客户端。
连接串 w=2:client.write_concern = {'w': 2}
集合上 with_options(write_concern=WriteConcern(w=1)):{'w': 1}
# mongosh:单次操作指定
test> db.t.insertOne({x: 1}, {writeConcern: {w: "majority", wtimeout: 5000}}).acknowledged
true连接串、集合、单次操作都可以指定写关注,单次操作的优先级最高。