说我有这个方法:
def create_registration_unless_over_limit
if Registration.count < 50
Registration.create!
else
raise "too many registrations"
end
end
考虑到我有多个rails进程正在运行,我如何确保我从未进行过&gt; = 50次注册?从理论上讲,两个请求几乎不可能同时进入,都运行if语句并查看&lt; 50个注册是真的,然后他们都创建了新的注册?
答案 0 :(得分:2)
对于你的特定情况,只要忽略这个问题:)我99.99%确定你真的不在乎你有50或51个注册:) 在更一般的情况下,您需要使用一些锁定。
SELECT count(*) FROM registrations FOR UPDATE
如果另一个线程执行了它并且仍然在事务中,则上述查询将阻止。
不幸的是'count'方法的ActiveRecord :: Base不支持:lock参数(嗯,为什么?)。所以你需要使用count_by_sql。请在2个独立的终端屏幕中尝试以下操作:
./script/runner 'Registration.transaction {puts "counting...";c = Registration.count_by_sql("select count(*) from registrations for update");puts "count = #{c}. press enter to continue";gets}'
当第一个运行将停在'按下进入'阶段时,第二个应该阻止在'计数...'阶段,直到你释放第一个。
答案 1 :(得分:0)
存储过程以创建行,如果&lt; 50,否则返回故障代码
或者!
创建一个创建帐户的队列系统,确保一个进程始终在创建帐户