0

给定用户和交易模型:

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

首先,我有一个竞争条件,使用 just 更新用户余额@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

还有一个问题,它是使用嵌套锁的好方法吗,例如当我需要在更新父模型的同时更新关系模型时?

4

1 回答 1

2

您需要根据数据库的内容(而不是您的 Rails 模型当前拥有的内容)通过添加/减去来直接更新数据库。看看update_counters

http://api.rubyonrails.org/classes/ActiveRecord/CounterCache/ClassMethods.html#method-i-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
于 2013-09-23T17:43:36.847 回答