在Rails ActiveRecord中生成序列号

时间:2012-11-08 14:43:22

标签: sql ruby-on-rails activerecord

在Rails应用程序中,我需要一个独特的,顺序(无间隙)整数的源,以用作序列号。它必须是持久的并允许并发访问。

数据库自动增量是不够的,因为大多数人都不保证“无间隙”属性。

在直接SQL中我只想创建一个单行表并说出(在PostgreSQL中)类似于:

update sequence set value = value + 1 returning value

这显然是SQL世界的标准做法。参考文献存在。

在ActiveRecord中,我轻松地为模型创建了一个模型,并在文档中找到了.increment!.increment_counter。但我无法弄清楚如何原子地检索增量值。锁和交易似乎没有帮助。

2 个答案:

答案 0 :(得分:2)

由于update ... returning的作用类似于输出目的,因此可以使用find_by_sql来更新并在一次操作中获取更新的值。

class SequenceNumber < ActiveRecord::Base
  attr_accessible :tag, :value
  validates :tag, :uniqueness => true

  def self.get_next(tag)
    find_by_sql("update sequence_numbers 
                 set value = value + 1 
                 where tag = '#{tag}' 
                 returning value").first.value
  end
end

剩下的问题是这完全不可移植,因为returning是pgsql扩展。也许ActiveRecord开发人员会注意到这一点。

答案 1 :(得分:0)

如果你想使用redis(也许你已经是因为Resque或Sidekiq),你可以对一个键执行INCR,这是原子并返回新值。