0

Rails アプリでは、シリアル番号として使用する一意の連続した (ギャップのない) 整数のソースが必要です。永続的であり、同時アクセスを許可する必要があります。

データベースの自動インクリメントは、ほとんどが「ギャップなし」のプロパティを保証しないため、適切ではありません。

単純な SQL では、1 行のテーブルを作成し、(PostgreSQL では) 次のように言います。

update sequence set value = value + 1 returning value

これは、SQL の世界では明らかに標準的な方法です。参照が存在します。

ActiveRecord では、モデルを簡単に作成し、ドキュメントで見つけまし.increment!.increment_counterしかし、インクリメントされた値をアトミックに取得する方法がわかりません。ロックとトランザクションは役に立たないようです。

4

2 に答える 2

2

update ... returning出力目的ではselectのように機能するため、1回の操作で更新と更新された値の取得の両方に使用できることがわかります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

残りの問題は、これがreturningpgsql拡張機能であるため、完全に移植性がないことです。たぶん、ActiveRecord開発者はこれに気付くでしょう。

于 2012-11-09T03:46:40.927 に答える
0

redisを使用したい場合(そしておそらくResqueまたはSidekiqが原因である場合)、INCRキーに対してonを実行できます。これはアトミックであり、新しい値を返します。

于 2012-11-08T15:45:22.617 に答える