正如我所见,我们可以从应用程序中设置写关注点,我想知道 MongoDB 将如何处理这样的场景:
假设我们有两个任务/进程(P1 和 P2)在同一个数据库上运行(数据库有一个由三个节点组成的副本集,1 个主节点和 2 个辅助节点)。P1 在日志级别启用了写入关注。P2 在副本级别启用了写入关注。(二级)。
现在如果 P1 和 P2 都写入数据库会发生什么?
P2会等待P1写入的数据复制到secondary,然后再将其数据写入secondary吗?
或者它是如何处理的?
正如我所见,我们可以从应用程序中设置写关注点,我想知道 MongoDB 将如何处理这样的场景:
假设我们有两个任务/进程(P1 和 P2)在同一个数据库上运行(数据库有一个由三个节点组成的副本集,1 个主节点和 2 个辅助节点)。P1 在日志级别启用了写入关注。P2 在副本级别启用了写入关注。(二级)。
现在如果 P1 和 P2 都写入数据库会发生什么?
P2会等待P1写入的数据复制到secondary,然后再将其数据写入secondary吗?
或者它是如何处理的?
写入关注点是每个操作,并确定 MongoDB 何时向客户端报告写入成功。它与大约同时发生的其他操作无关。
如果 P1 具有“在日志级别启用写关注”,我认为这意味着日志写关注{ "j" : 1 }
,MongoDB 不会报告 P1 发送的操作成功,直到它们被提交到日志。P2 写入的状态无关紧要。
如果 P2 具有“在副本级别启用写关注”,我认为这意味着多数写关注{ "w" : "majority" }
,那么 P2 所做的每个操作都不会被报告为成功,直到它复制到副本集中的大多数节点。P1 写入的状态无关紧要。
P1 和 P2 操作不会等待对方的写关注得到满足,然后再继续,或类似的事情。
由于响应很长,因此编辑了对答案的评论回复:
是的,第二次写入必须等待第一次写入释放数据库写入锁(如果第一次写入产生锁,可能在多文档第一次写入的中间),但第二次写入没有等待第一次写入完成其整个写入关注点。
例如,考虑一个 write A
with{ "w" : "majority" }
和一个 write B
with { "w" : 1 }
。A
首先到达主节点并获取写锁。B
第二个到达并等待写锁。A
完成使用写锁并释放它;B
拿锁。的写入需要被复制到辅助节点以实现其写入问题——这与持有写入锁A
同时发生。完成并且 MongoDB 响应客户端写入成功。完成复制到所需数量的副本集成员,MongoDB 响应写入成功。之前发送过并写在主要之前B
B
A
A
B
B
,在此期间它持有锁并阻塞B
,但B
首先返回。这不是写问题,更简单的事实是A
MongoDBB
不能一次对同一个数据库进行两次写入。
这个问题很老了,大约是 Mongo 迁移到 WiredTiger (2015) 3.0 版的时候。从那时起,引擎的并发性显着提高,对于大多数读/写操作,锁定级别是文档级别本身。
见:https ://docs.mongodb.com/manual/faq/concurrency/
因此,多线程(相同进程或多进程)也可以提高最严格的写入问题的性能。