乐观锁、悲观锁处理并发

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yqwang75457/article/details/84345967

处理并发问题,我们可以从2个层面去解决(这里我只做简单的介绍,方便理解记忆):

1.代码层面

常用的就是synchronize同步、ThreadLocal本地复制,这里不过多解释

2.数据库层面

2.1:悲观锁

假设一PersonA要对某条数据进行修改,那么查询这条数据修改这条数据,可以对这条数据进行加锁,sqlA(CMD窗口1):

begin;

select * from table where id = 1 for update;

update update table xx='AA' where id = 1;

commit;//在此之前,其他地方的代码,将不能修改id=1这条数据

PersonB也要对id=1的这条数据进行update,那么sqlB(CMD窗口2): update table xx='BB' where id = 1;

如果sqlA还没有执行commit;语句,那么sqlB是不能执行成功的。因为sqlA把id=1的这条数据进行了加锁。

只有等待sqlA执行了commit;提交事务语句,sqlB才能成功执行。

即:本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。 

悲观锁存在的问题:如果这个事务整体中,需要花费大量的时间处理业务逻辑再commit;那么久意味着这段时间内,这条数据都处于加锁状态,其他业务逻辑或者其他系统将无法对这条数据进行操作。

那如何解决这个问题呢?答案:乐观锁

2.2:乐观锁

乐观锁策略:提交版本必须大于记 录当前版本才能执行更新 

原理:需要在表中添加version字段,每次需要修改数据之前,查询数据的时候需要把这个version查询出来,修改好其他属性值,执行update之前,修改version值(version+1)。如果满足修改后的version大于数据库的version,再执行update。

比如:update table set name = 'xxx' and version = (修改后的version) where id = 1 and version < 修改后的version

举例:

1.操作员A得到一条数据{id:1,value:100,version:1},开始在页面上进行编辑操作,version=version+1 = 2,也就是改成了{id:1,value:50,version:2},

2.操作员A在提交本次修改之前,操作员B得到的数据依然是{id:1,value:100,version:1},开始在页面上进行编辑操作,version=version+1 = 2(version也是等于2),改成了{id:1,value:150,version:2},

3.操作员B提交修改操作之前,操作员A提交事务,A的提交版本(值=2) > 数据库version值1,满足条件,提交成功,这时数据库数据就是{id:1,value:50,version:2},那现在操作员B提交事务,B的提交版本(值=2) > 数据库version值1,不成立,不执行提交。

由此可见:乐观锁机制避免了脏数据的产生,同时避免了长事务中的数据库加锁开销。

更多详细的描述建议查看:https://www.cnblogs.com/sheseido/p/5038562.html

如果需要在web应用中用代码或者配置体现出来,建议执行上网查询

猜你喜欢

转载自blog.csdn.net/yqwang75457/article/details/84345967