Ruby on rails 在ruby v 2.1.3中设置隔离级别

Ruby on rails 在ruby v 2.1.3中设置隔离级别,ruby-on-rails,activerecord,isolation-level,transaction-isolation,Ruby On Rails,Activerecord,Isolation Level,Transaction Isolation,我一直在努力在我的表上设置一个记录级锁,以避免在更新记录时出现任何脏读和争用情况。 我使用的是ruby 2.1.3和rails版本3.2.13。我尝试使用以下命令: Account.connection.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE") 并通过放置sleep进行测试,但试图更新同一记录的两个进程读取了旧值,而最终数据是错误的。例如:如果我的旧值为100,则两个进程都读取100,然后更新100+x和100+y,因此,数

我一直在努力在我的表上设置一个记录级锁,以避免在更新记录时出现任何脏读和争用情况。 我使用的是ruby 2.1.3和rails版本3.2.13。我尝试使用以下命令:

Account.connection.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")
并通过放置sleep进行测试,但试图更新同一记录的两个进程读取了旧值,而最终数据是错误的。例如:如果我的旧值为100,则两个进程都读取100,然后更新100+x和100+y,因此,数据被破坏


我正在使用mySQL数据库。非常感谢您的帮助。

Rails中支持两种锁定机制:和

使用悲观锁定更新帐户余额应如下所示:

acc = Account.find(id)
acc.with_lock do
  acc.balance += 100
  acc.save!
end

以下解决方案对我有效(对dimakura的答案稍加修改):

  • 当我将find()用于活动记录查询时:

    acc = Account.lock.find(id)
    acc.balance += 100
    acc.save!
    
    acc = Account.where(:acc_code => acc_code).first
    acc.with_lock do
     acc.balance += 100
     acc.save!
    end
    
  • 当我将where()用于活动记录查询时:

    acc = Account.lock.find(id)
    acc.balance += 100
    acc.save!
    
    acc = Account.where(:acc_code => acc_code).first
    acc.with_lock do
     acc.balance += 100
     acc.save!
    end
    

  • 谢谢1例有效。仍在处理其他案件。完成后将进行更新。我还需要知道,如果变量acc为空(即不存在活动记录,acc.with_lock会引发一些异常,还是会执行块?您能帮帮忙吗?提前感谢!如果
    acc
    nil
    (空白)它将引发
    方法未定义
    异常。您需要在启动块之前检查此项。