2010-04-16 60 views
0

我在before_save一些逻辑由此(仅)当某些条件被满足我让新行special_number等于在数据库+ 1的最大special_number被创建(如果条件不符合,我做一些不同的事情,所以我不能使用自动增量)ActiveRecord的和before_save`和`save`之间`transactionsin

我担心的是,一次在这个数据库上运行的两个线程可能会选择相同的special_number如果第二个执行时首先是保存。有没有办法锁定before_save之间的数据库和完成保存,但只在某些情况下?我知道所有的保存都是以交易方式发送的,这会帮助我完成这项工作吗?

def before_save 
    if things_are_just_right 
    # -- Issue some kind of lock? 
    # -- self.lock? I have no idea 
    # Pick new special_number 
    new_special = self.class.maximum('special_number') + 1 
    write_attribute('special_number',new_special) 
    else 
    # No need to lock in this case 
    write_attribute('special_number',some_other_number) 
    end 
end 

回答

1

如果特殊号码总是增加1,和你不能有“缺口”,它的保存在DB-你可以使用select进行更新:

SELECT special_num FROM nums FOR UPDATE; 
UPDATE nums SET special_num = special_num + 1; 

你可以阅读它在这里:select for update

请注意,它锁定了数据库,因此如果您有大量更新以使用特殊数字,则可能会出现性能问题。

如果你没有在特殊NUM心中有差距(如果交易失败)一个简单的方法是使用memcahced“INC”功能,因为这将瓶坯非常快:)

+0

我没有实际使用MySQL! (heroku + sqlite3) - 我不认为sqlite具有相同的功能? – 2010-04-16 10:18:02

相关问题