乐观锁

作者:周星 发布:2014-07-03

       在更新数据库记录的时候,“锁”有时特别重要,当两个人同时更新一条记录的时候,后一个人的更新会把前一个人的更新覆盖掉,而后一个人却对此毫不知情。假设 people 表里有这样一条记录:(name:星哥, sex: male, position: developer),两个人都点击了“编辑”按钮进入了编辑界面,第一个人把这条记录的 name 字段改成了“星弟”,并点击了提交,此时这条记录是:(name:星弟, sex: male, position: developer);第二个人把这条记录的 position 字段改成了“CEO”,但是他在编辑界面看到的 name 字段的值仍然是“星哥”,但是他不知道有人把这个字段改成了“星弟”,所以他很自然的点击了“提交”,这条记录的 name 字段又变回了“星哥”,这不符合我们的需求。

       在一些并发量小的项目里,这种情况可能不会被“经验较少”的程序员遇到,当并发量大了之后,这就是我们必须要处理的问题了。尤其是在一些涉及到钱之类的功能里,这个时候,我们就要用到“锁”,本次分享,我们主要来学习一下 rails 中的乐观锁(Optimistic Locking)。
       乐观锁允许多个用户去编辑同一条记录,并且假定了数据的最小冲突,乐观锁通过检查当一条记录被编辑的时候,是否有其他的程序已经对其进行了更新,如果有,则会抛出一个 ActiveRecord::StaleObjectError 异常并且忽略更新操作。 

       那么“乐观锁”是怎么达到这一目的的呢? 

       首先,我们要在需要使用“乐观锁”的表上增加一个 lock_version 字段,它的默认值一定要为0!每一次记录被更新的时候, ActiveRecord 会使这条记录的 lock_version 值自增 +1,如果一个 update 请求传给后端的 lock_version 值低于这条记录在数据库中的 lock_version值,则更新失败,然后抛出那个异常。

c1 = Client.find(1)
c2 = Client.find(1)

c1.first_name = "Michael"
c1.save

c2.name = "should fail"
c2.save # Raises an ActiveRecord::StaleObjectError

然后我们就可以根据捕获的异常来进行各种处理了。

通过设置 ActiveRecord::Base.lock_optimistically = false,可以关闭“乐观锁”这一特性。

如果不想使用默认的 lock_version 字段,可以通过在 model 里声明 set_locking_column 来重命名

class Boy< ActiveRecord::Base
  set_locking_column :lock_client_column
end

如果对本分享有什么疑问,请联系作者。

支付宝扫码赞助博主


评论(0)