通过find_or_create_by_创建重复记录 [英] Duplicate Records created by find_or_create_by_

查看:342
本文介绍了通过find_or_create_by_创建重复记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ActiveRecord对象,公司和我的项目中只调用创建实例的这个对象是这样的:

I have an ActiveRecord object, Corporation, and the only call in my project to create instances of this object looks like:

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

然而不知何故,在我的应用程序已经愉快地运行了几天,有重复的记录 - 记录那里的eveid和USER_ID有相同的价值观。这怎么可能?有什么在我更新这些记录的方式,将导致此问题,我可以做的不对吗?

Yet somehow, after my application has been running happily for a couple of days, there are duplicate records -- record where the eveid and user_id have the same values. How is this possible? Is there something I could be doing wrong in the way I update these records that would cause this problem?

我最后增加了一个独特的,综合指数表。这应该解决这个问题,但我不知道它是如何发生的。

I ended up added a unique, composite index to the table. That should solve the problem, but I don't understand how it's occurring.

这是Rails的3.0.7。

This is Rails 3.0.7.

推荐答案

find_or_create 不执行任何锁定,并没有试图prevent竞争条件。这只是一个方便的方法。如果比赛条件是一个问题,你将需要:

find_or_create does not perform any locking and makes no attempt to prevent race conditions. It's just a convenience method. If race conditions are a problem, you will need to either:

  1. 使用事务和回退,如果你发现别人写你
  2. 之前
  3. (更好,如果你实际上是在期待一个竞争条件),则执行保守式锁定。这是你从表中获取的排它锁,再进行写入和清除锁定选择。在MySQL的InnoDB表,这是 SELECT ... FOR UPDATE 。如果你没有参考点锁定(即没有外键或任何已经存在于数据库中),那么你就必须坚持(1)。
  1. Use a transaction and roll back if you find somebody else has written just before you
  2. (Better if you're actually expecting a race condition), perform pessimistic locking. This is where you SELECT from the table acquiring an exclusive lock first, then perform the write and clear the lock. In MySQL InnoDB tables, this is SELECT ... FOR UPDATE. If you have no reference point to lock on (i.e. no foreign key or anything that already exists in the database), then you'll have to stick with (1).

编辑|如果你能在架构层面增加唯一约束,我建议这样做太,如果这是一个真正的完整的关切。

EDIT | If you can add a UNIQUE constraint at the schema level, I'd advise doing so too, if this is a genuine integrity concern.

这篇关于通过find_or_create_by_创建重复记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆