0

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

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

在直接的 SQL 中,我将创建一个单行表并说(在 PostgreSQL 中)类似:

update sequence set value = value + 1 returning value

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

在 ActiveRecord 中,我轻松地创建了模型.increment!.increment_counter在文档中找到了模型。但我不知道如何以原子方式检索增加的值。锁和交易似乎没有帮助。

4

2 回答 2

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 开发人员会注意到这一点。

于 2012-11-09T03:46:40.927 回答
0

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

于 2012-11-08T15:45:22.617 回答