乐观锁的实现

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作 

悲观锁,从字面理解就是很悲观,每次去拿数据的时候都认为别人会修改,所以在每次拿的时候对数据上锁,这样就保证了数据的准确性。比如mysql中的表锁,行锁。

表锁:当你对一张表进行修改时,会锁死整张表,其他的请求需要在修改完成释放锁才能继续。在高并发的情景下不适用。

行锁:当你对一张表的某一行数据修改时,会锁死这一行数据,对表中其他的数据没影响。行锁在保证数据准确性的同时也保证了效率,但一定程度上增加了系统的开销。

乐观锁: 假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。

乐观锁,在每次去拿数据的时候认为别人不会修改,不对数据上锁,但是在提交更新的时候会判断在此期间数据是否被更改,如果被更改则提交失败。
 

乐观锁的实现

使用版本控制字段,再利用行锁的特性实现乐观锁

如下

有一张用户表user,有字段 id 、 age,  为实现乐观锁控制,添加version字段,默认值0                

                                                                        user表

id 1
age20      
version 


假设两个人同时进来修改该条数据,操作为:

1. 先查询该数据   select * from user where id = 1

2. 修改该条数据  update user set age= 21 where id = 1

如果两个人同时查询到该条数据age= 20, 可以执行update操作, 但任意一方还没执行update操作,那么最后双方都执行update,导致数据被修改两次,产生脏数据 !

使用version字段控制版本后:

1. 两人先查询该数据 select * from user where id = 1

此时两人查询到的数据一样,id = 1, age= 20, version = 0

2. 两人都发现该条数据 age= 20, 符合update条件,第一人执行update(因为mysql行锁的特性,两人不可能同时修改一条数据,所以update同一条数据的时候,是有先后顺序的,只有在第一个执行完update,才能释放行锁,第二个继续进行update): 

update user set age= 22, version = version + 1 where id = 1 and version = 0

执行完成后,version字段值将变成1, 第二人执行update:

update user set age= 25, version = version + 1 where id = 1 and version = 0

此时的version的值已经被修改为1,所以第二人修改失败,实现乐观锁控制。

死锁的处理
数据库使用乐观锁导致产生死锁:

事务A
update user set age = 21 where id = 1

 update user set age = 22 where id = 2

事务B
update user set age = 21 where id = 2

update user set age = 22 where id = 1

假设在两个事务中有以上两个操作,同时修改order表中两条数据

事务A在执行完第一条update的时候,刚好事务B也执行完第一条update

此时, 事务A中user表中的id = 1的行被锁住, 事务B中user表中id = 2的行被锁住,两个事务继续往下执行

事务A中第二条update执行需要user表中id = 2的行数据,而事务B中第二条update执行需要id = 1的行数据, 两条update往下执行的条件都需要对方事务中已经被锁住的行,于是陷入无限等待,形成死锁。

解决死锁的产生

指定锁的执行顺序,比如把以上两事务稍作修改

事务A



update user set age = 22 where id = 2

update user set age = 21 where id = 1

事务B



update user set age = 21 where id = 2

update user set age = 22 where id = 1

事务A执行第一条update时,id = 2 的行被锁住,此时,事务B想修改id = 2的行,只能等待事务A执行完成,当事务A执行完成时,事务B再执行, 这样就不会产生死锁了。
 
 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值