给定用户和交易模型:
class User < ActiveRecord::Base
has_many :transactions
end
class Transaction < ActiveRecord::Base
belongs_to :user
end
API过于频繁出现问题:
def trx
User.transaction do
user = User.where(id: @data.user.id).lock(true).first
trx_number = user.transactions.count + 1
# some work
user.transactions.create(...)
change_balance = ...
user.balance = user.balance.to_f + change_balance.to_f
inform_user = user.has_valid_informee
if !result && inform_user
inform_user.balance = inform_user.aff_balance.to_f + @amount.to_f
inform_user.save!
end
user.save!
end
end
首先我有一个竞争条件,只使用@data.user
更新用户余额,有时新请求在之前完成,因此我们丢失了一些数据。相反,我开始请求锁定该用户。
接下来的竞争条件是计算总交易量,现在我看到它们将有另一个带有inform_user的RC。
所以问题是我做错了吗?使用以下方法重写inform_user的更新余额是否是一种好方法:
inform_user.with_lock do
inform_user.balance = inform_user.aff_balance.to_f + @amount.to_f
end
另一个问题是,这是一种使用嵌套锁的好方法,例如我需要在更新父模型时更新关系模型吗?
答案 0 :(得分:2)
您需要根据数据库的内容(而不是Rails模型当前具有的内容)添加/减去直接更新数据库。看看update_counters
。
# For the Post with id of 5, decrement the comment_count by 1, and
# increment the action_count by 1
Post.update_counters 5, comment_count: -1, action_count: 1
# Executes the following SQL:
# UPDATE posts
# SET comment_count = COALESCE(comment_count, 0) - 1,
# action_count = COALESCE(action_count, 0) + 1
# WHERE id = 5