unique index如何解决RoR中validates_uniqueness_of中的race condition?
How does unique index solve the race condition in validates_uniqueness_of in RoR?
我知道
有问题
validates_uniqueness_of :attribute
在 RoR 中,因为在极少数情况下存在竞争条件,即有两个请求,一个紧接着另一个。
我读过的解决方案是为每个模型请求放置一个单独的唯一索引,这会在竞争条件的情况下引发错误。
我不明白这是怎么回事。
如果 A 提出请求,那么 B 会为他们分配相同的索引吗?这是如何运作的?
出现竞争条件是因为rails无法锁定数据库并且经常同时运行多个线程。
要了解竞争条件是如何发生的,请考虑唯一性检查需要什么,我将举两个线程的示例:
假设 A 和 B 想要保存一个新的 BlogPost,其属性 name
必须是唯一的。
- A 点了保存按钮
- B 点了保存按钮
- Rails 启动线程 A 并查询数据库以查看是否
有任何名为 "My BlogPost"
的博文
- Rails 启动线程 B 并查询数据库以查看是否有任何名为 "My BlogPost"
的博客文章
- 线程 A returns "nope, no blogposts with that name, all clear to save"
- 线程 B returns "nope, no blogposts with that name, all clear to save"
- 话题 A 保存了 A 的博文
- 线程 B 也是如此
...现在有两个同名的博文。
没有什么可以阻止这种情况的发生,这是因为 "lookup[" 和 "save" 操作是两个独立的事情..因此可以以上述方式发生。
但是......当你在数据库上放置唯一索引时......会发生什么:
- A 点了保存按钮
- B 点了保存按钮
- Rails 启动线程 A 并查询数据库以查看是否
有任何名为 "My BlogPost"
的博文
- Rails 启动线程 B 并查询数据库以查看是否有任何名为 "My BlogPost"
的博客文章
- 线程 A returns "nope, no blogposts with that name, all clear to save"
- 线程 B returns "nope, no blogposts with that name, all clear to save"
- 话题 A 保存了 A 的博文
- 线程 B 试图保存博文,但数据库显示 "NOPE! I failed a uniqueness constraint"
结果:只有一篇博文具有该名称。
现在 - 对于您所问的...我假设是错误的理解...索引不是 id。
每条记录不会获得相同的索引。
没有记录获得索引。
您可以假装索引是对已为此列设置的所有值的查找-table。
非唯一索引的情况是您拥有所有值的列表……以及具有该值的记录的列表。例如:
小部件:
颜色:
蓝色 ID:1,3,7
绿色 ID:2,4
红色 ID:5,6
(完全是虚构的例子,与现实完全不同)
当索引具有唯一性约束时,它只有相同的列表,但只允许数据库为每个值存储 一个 id,如果您尝试存储另一个。 .. 引发异常
我知道
有问题validates_uniqueness_of :attribute
在 RoR 中,因为在极少数情况下存在竞争条件,即有两个请求,一个紧接着另一个。
我读过的解决方案是为每个模型请求放置一个单独的唯一索引,这会在竞争条件的情况下引发错误。
我不明白这是怎么回事。 如果 A 提出请求,那么 B 会为他们分配相同的索引吗?这是如何运作的?
出现竞争条件是因为rails无法锁定数据库并且经常同时运行多个线程。
要了解竞争条件是如何发生的,请考虑唯一性检查需要什么,我将举两个线程的示例:
假设 A 和 B 想要保存一个新的 BlogPost,其属性 name
必须是唯一的。
- A 点了保存按钮
- B 点了保存按钮
- Rails 启动线程 A 并查询数据库以查看是否 有任何名为 "My BlogPost" 的博文
- Rails 启动线程 B 并查询数据库以查看是否有任何名为 "My BlogPost" 的博客文章
- 线程 A returns "nope, no blogposts with that name, all clear to save"
- 线程 B returns "nope, no blogposts with that name, all clear to save"
- 话题 A 保存了 A 的博文
- 线程 B 也是如此
...现在有两个同名的博文。
没有什么可以阻止这种情况的发生,这是因为 "lookup[" 和 "save" 操作是两个独立的事情..因此可以以上述方式发生。
但是......当你在数据库上放置唯一索引时......会发生什么:
- A 点了保存按钮
- B 点了保存按钮
- Rails 启动线程 A 并查询数据库以查看是否 有任何名为 "My BlogPost" 的博文
- Rails 启动线程 B 并查询数据库以查看是否有任何名为 "My BlogPost" 的博客文章
- 线程 A returns "nope, no blogposts with that name, all clear to save"
- 线程 B returns "nope, no blogposts with that name, all clear to save"
- 话题 A 保存了 A 的博文
- 线程 B 试图保存博文,但数据库显示 "NOPE! I failed a uniqueness constraint"
结果:只有一篇博文具有该名称。
现在 - 对于您所问的...我假设是错误的理解...索引不是 id。 每条记录不会获得相同的索引。 没有记录获得索引。
您可以假装索引是对已为此列设置的所有值的查找-table。
非唯一索引的情况是您拥有所有值的列表……以及具有该值的记录的列表。例如:
小部件: 颜色: 蓝色 ID:1,3,7 绿色 ID:2,4 红色 ID:5,6
(完全是虚构的例子,与现实完全不同)
当索引具有唯一性约束时,它只有相同的列表,但只允许数据库为每个值存储 一个 id,如果您尝试存储另一个。 .. 引发异常