由find_or_create_by_创建的重复记录

我有一个ActiveRecord对象,公司,我的项目中唯一一个调用此对象的实例的调用如下所示:

corp = Corporation.find_or_create_by_eveid_and_user_id(self.corporation_eveid, self.account.user_id) 

然而,不知何故,在我的应用程序快乐地运行了几天后,有重复的记录 – 记录eveid和user_id具有相同的值。 这怎么可能? 在我更新这些会导致此问题的记录的方式中,我可能做错了吗?

我最终为表添加了一个唯一的复合索引。 这应该可以解决问题,但我不明白它是如何发生的。

这是Rails 3.0.7。

find_or_create不执行任何锁定,也不会尝试阻止竞争条件。 这只是一种方便的方法。 如果竞争条件有问题,您需要:

  1. 如果您发现其他人已在您之前撰写,请使用交易并回滚
  2. (如果你真的期待竞争条件会更好),执行悲观锁定。 这是您从表中首先获取独占锁定,然后执行写入并清除锁定的位置。 在MySQL InnoDB表中,这是SELECT ... FOR UPDATE 。 如果没有锁定参考点(即没有外键或数据库中已存在的任何东西),那么你必须坚持使用(1)。

编辑| 如果您可以在架构级别添加UNIQUE约束,我建议也这样做,如果这是一个真正的完整性问题。

这是你的种子文件吗? 您最好的选择是在模型中编写validation,以防止存在具有相同eveid和user_id的公司。

在我看来,你使用find_or_create播种了这些信息。 但是,也许在当天晚些时候或者另一天,有人使用您的GUI创建了另一个具有相同信息的人。 validation会阻止这种情况。

我没有测试过这段代码,但是这样的东西可能对你有用。

 validates :eveid, :uniqueness => { :scope => :user_id }