独特索引如何解决RoR中validates_uniqueness_of中的竞争条件?

时间:2016-06-09 05:01:58

标签: ruby-on-rails race-condition

我知道

存在问题
validates_uniqueness_of :attribute 

在RoR中,由于竞争条件极少,有两个请求,一个紧接着另一个请求。

我读过的解决方案是为每个模型请求添加一个单独的唯一索引,这会在竞争条件下引发错误。

我不明白这是怎么回事。 如果Person A发出请求,然后是Person B,他们会被分配相同的索引?这是如何运作的?

1 个答案:

答案 0 :(得分:2)

竞争条件发生是因为rails无法锁定数据库并且经常同时运行多个线程。

要了解竞争条件是如何发生的,请考虑一下唯一性检查所需要的内容,我将举两个主题的例子:

假设人A和B想要保存一个新的BlogPost,其属性name必须是唯一的。

  1. 人物A点击保存按钮
  2. 人员B点击保存按钮
  3. Rails启动线程A,然后查询数据库以查看是否 有任何BlogPosts的名称"我的BlogPost"
  4. Rails启动线程B,然后查询数据库以查看是否有任何名为"我的BlogPost"
  5. 的BlogPosts
  6. 线程A返回" nope,没有带有该名称的博客帖子,全部清除以保存"
  7. 线程B返回" nope,没有具有该名称的博客帖子,全部清除以保存"
  8. 主题A保存人员A的博客帖子
  9. 线程B
  10. 也是如此

    ......现在有两个同名的博客帖子。

    没有什么可以阻止这种情况发生,这是因为"查找["并且"保存"动作是两个独立的事物......因此可以以上述方式发生。

    然而......当你在数据库上放一个唯一索引时......会发生什么:

    1. 人物A点击保存按钮
    2. 人员B点击保存按钮
    3. Rails启动线程A,然后查询数据库以查看是否 有任何BlogPosts的名称"我的BlogPost"
    4. Rails启动线程B,然后查询数据库以查看是否有任何名为"我的BlogPost"
    5. 的BlogPosts
    6. 线程A返回" nope,没有带有该名称的博客帖子,全部清除以保存"
    7. 线程B返回" nope,没有具有该名称的博客帖子,全部清除以保存"
    8. 主题A保存人员A的博客帖子
    9. 线程B尝试保存博客帖子,但数据库说" NOPE!我没有一个唯一性约束"
    10. 结果:只有一个名为。

      的BlogPost

      现在 - 你所问的......以及我所假设的是错误的理解......并且索引不是id。 每条记录都没有获得相同的索引。 没有记录获得索引。

      您可以假装索引是已为此列设置的所有值的查找表。

      非唯一索引会发生的情况是,您拥有所有值的列表...以及哪些记录具有该值的列表。例如:

      窗口小部件: 颜色: 蓝ids:1,3,7 绿ids:2,4 红ids:5,6

      (完全是一个例子,没有现实)

      当索引具有唯一性约束时,它只有相同的列表,但只允许db为每个值存储一个 id,如果你试图存储另一个...它会引发一个例外