乐观锁与悲观锁的使用场景?我们如何在 Rails 中使用它们?以及锁的作用范围区间?

丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新。

脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6,用户B把值改为2,用户A读到的值仍为6。

乐观锁:

适用于资源争用不激烈(数据更新不频繁)的时候使用,乐观锁定允许多个用户访问并编辑同一记录,并假设数据发生冲突的可能性最小。其原理是检查读取记录后是否有其他进程尝试更新记录,如果有就抛ActiveRecord::StaleObjectError 异常,并忽略该更新

使用:

 每次更新记录时,Active Record 都会增加 lock_version 字段的值。如果更新请求中 lock_version 字段的值比当前数据库中 lock_version 字段的值小,更新请求就会失败,并抛出 ActiveRecord::StaleObjectError 异常通过设置 ActiveRecord::Base.lock_optimistically = false 可以关闭乐观锁定

user1 = User.find(1)       

user2 = User.find(1)

user1.update(:age => 20)

user1.save

user2.update(:age => 30)

user2.save  #会抛出ActiveRecord::StaleObjectError异常

悲观锁:

 悲观锁适用于资源争用比较严重(数据更新频繁)的时候使用,悲观锁定使用底层数据库提供的锁定机制。在创建关联时使用 lock 方法,会在选定字段上生成互斥锁。使用 lock 方法的关联通常被包装在事务中,以避免发生死锁

User.lock.find(1)  #会导致行锁

User.where(:name => guo).lock(true).first  #会导致表锁

mysql innodb 里面,对于 "select * from where xxx for update" 的情况,是会锁住整张表Rails 也提供了一个很方便的方法 with_lock 来锁住单个记录,并且内嵌在事务之中

user = User.find(1)

user.with_lock do
user.age = 30

user.save
 end

悲观锁出错概率小,因为一旦获得锁,其他进程会堵塞,但是也导致速度会受影响,系统开销比较大,不利于并发。乐观锁适用于资源竞争不是那么多的地方,这样系统的开销较小,速度也比较快。都是为了解决高并发情况,类似于java上的同步、异步锁机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值