独特的索引如何真正起作用并避免碰撞?

时间:2015-05-13 16:16:27

标签: mongodb indexing duplicates unique-constraint

假设我有一个集合,我在字段上创建一个唯一索引:

db.users.createIndex({username: 1}, {unique:true})

如果两个具有相同用户名的文档同时插入集合中会发生什么?
数据库如何防止碰撞?我的意思是哪一个插入,哪个导致错误?
假设插入是真的同步,数据库无法知道插入了两个重复项,对吧?
那么,真正发生了什么?

1 个答案:

答案 0 :(得分:6)

无法同时将数据应用于数据集。当写入发送到MongoDB实例时,无论是分片还是独立服务器,都会发生以下情况

  1. 请求集合范围的写锁定(驻留在RAM中)
  2. 当授予锁定时,将根据唯一索引(通常驻留在RAM中)检查要写入的结果数据(无论是更新,upsert还是新文档)
  3. 如果没有冲突,数据将应用于RAM中的数据集
  4. 锁被释放。只有现在其他写入才能开始对内存中的数据进行更改。
  5. 使用默认的写入问题,查询现在返回
  6. commitIntervalMs数据写入日记
  7. 之后
  8. 仅在syncInterval秒后(默认为60),日记应用于数据文件
  9. 话虽如此,我们可以看看实际值。对于单个服务器来说,100万次写入/秒似乎有点多(仅仅因为大容量存储无法处理它),因此我们假设一个带有10个分片的分片群集,其中一个分片键可以或多或少均匀地分配写入。如上所述,所有操作都应用于RAM。使用今天的硬件,可以处理大约35亿条指令/秒,或者每纳秒3.5条指令。让我们假设获得和释放一个锁,每个指令需要35个指令或10纳秒。所以我们每次100k写入的锁定和解锁都需要20纳秒,总共是1/500秒。

    对于MongoDB需要做的其他事情,这将留下499/500秒或998000000纳秒,这意味着高达3.493 十亿指令。

    防止并发写入的锁定远不是写入操作的限制因素。将更改同步到日志和数据文件通常是限制因素,然后减少RAM以将索引和工作集保存在RAM中。