MongoDB 4.2.11单节点副本集fsync加锁后取消的写入仍被持久化是否正常
问题结论
该现象属于预期行为,并非MongoDB fsync功能的已知bug。
核心原理说明
- 带
lock: true参数的fsync命令执行逻辑为:先将内存中所有未持久化的写入操作刷入磁盘,之后阻塞所有新写入操作的结果返回,但不会丢弃已经被服务端成功接收、进入等待队列的写入任务。 - 操作中提及的「手动取消写入」,本质仅终止了客户端侧的请求等待链路,并未向MongoDB服务端发送丢弃对应写入任务的指令,该写入请求仍然保留在服务端的待执行队列中。
- 执行
fsyncUnlock解锁后,服务端会按顺序执行队列中所有积压的写入请求,此前在客户端取消的写入任务会被正常执行、最终持久化到数据库。
场景验证方法
可通过如下步骤复现验证上述逻辑:
- 执行
db.runCommand({fsync:1, lock:true})完成加锁 - 发起写入请求,待客户端提示阻塞后手动取消客户端请求
- 解锁前执行对应数据的查询操作,可确认数据暂未写入
- 执行
db.fsyncUnlock()解锁后再次查询,可看到数据已成功写入
规避方案
如果需要避免这类积压写入在解锁后被执行,可在解锁前先通过db.currentOp()检索到对应的写入会话,调用db.killOp(<操作ID>)手动终止该会话后再执行解锁操作即可。
内容的提问来源于stack exchange,提问作者Vineel
相关产品推荐
相关产品推荐

