【问题标题】:How do unique indexes really work and avoid collisions?唯一索引如何真正起作用并避免冲突?
【发布时间】:2015-07-25 01:28:39
【问题描述】:

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

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

如果将两个具有相同用户名的文档同时插入到集合中会怎样?
数据库如何防止冲突?我的意思是哪个被插入,哪个导致错误?
假设插入确实是同时进行的,那么数据库无法知道正在插入两个重复项,对吗?
那么,到底发生了什么?

【问题讨论】:

  • 简单来说,哪个insert先拿到写锁就赢,另一个insert会出错。
  • @JohnnyHK,你是说不可能同时获得写锁吗?
  • 这就是为什么唯一索引还不能存在于分片 envos atm 中的分片键之外的原因
  • 数据首先应用到内存中,因此获得锁是纳秒级的问题。并且 1M 写入很可能在单个服务器上是不可行的。在共享环境中,新文档将被发送到具有匹配键范围的分片。如果做得好,您的写入将或多或少均匀分布(模糊)。假设您有 10 个分片,这将转换为 100k 写入/分片/秒。即使每次取锁和解除锁都需要 10ns,也就是 2M 纳秒或 1/500 秒。还有很多时间去做其他事情。
  • @SylvainLeroux 我已将答案添加为社区 wiki。

标签: mongodb indexing duplicates unique-constraint


【解决方案1】:

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

  1. 请求集合范围的写锁(驻留在 RAM 中)
  2. 授予锁定后,将根据唯一索引(通常驻留在 RAM 中)检查要写入的结果数据(无论是更新、更新插入还是新文档)
  3. 如果没有冲突,则将数据应用到数据集在 RAM 中
  4. 锁被释放。只有现在其他写入才能开始对内存中的数据进行更改。
  5. 使用默认写入关注点,查询现在返回
  6. commitIntervalMs 后数据写入日志
  7. 仅在 syncInterval 秒(默认为 60)之后,日志才会应用于数据文件

话虽如此,我们可以看看实际值。每秒 100 万次写入对于单个服务器来说似乎有点多(仅仅是因为大容量存储无法处理它),因此我们假设一个具有 10 个分片的分片集群,其分片键或多或少地平均分配写入。正如我们在上面看到的,所有操作都应用在 RAM 中。使用今天的硬件,每秒可以处理大约 35 亿条指令,即每纳秒 3.5 条指令。假设获取和释放锁每个需要 35 条指令或 10 纳秒。因此,每次 10 万次写入的锁定和解锁都需要 20 纳秒,总共是 1/500 秒。

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

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

【讨论】:

  • 我同意您回答的上半部分,但我不同意根据 CPU 每秒处理 X0 亿条指令的能力来估计锁定和解锁速度。正如您正确指出的那样,所涉及的实际 CPU 指令所花费的时间可以忽略不计。但这既不是这里也不是那里。您应该查看内存读写速度。
  • 老实说:这只是猜测。但是获取和释放锁与实际操作数据之间的关系应该是正确的,这就是我的观点。由于我故意将其发布为社区 wiki 答案,请随时根据实际值对其进行编辑。
  • 获取锁所需的时间取决于 CPU 速度和 CPU 数量。更多 CPU == 获取锁的时间更长。此外,在 MongoDB 3.0 (MMAPv1) 中引入了集合级别的锁,在以前的版本 (2.2/2.4/2.6) 中它是数据库级别的,在 2.0 和更早版本中它是全局的。对于这样的事情。数据实际写入内存的方式也存在一些不准确之处。有数据的共享视图和私有视图的概念。更新都发生在共享视图中,共享视图是原子更新的。
  • @PeteGarafano 这是一个社区 wiki 答案,您的见解将是一个很好的补充(我不会用它来研究代表,因为没有人会获得 wiki 答案的代表)
  • 作为参考,这是一个很好的赞美:stackoverflow.com/a/17459488/383478
猜你喜欢
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 2011-07-02
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多