Mysql乐观锁为什么可以防止并发

问题引入

本文介绍的是最常用的也是mysql默认的innoDB引擎 Read committed隔离级别下事物的并发。这种情况下的事物特点是

读:在一个事物里面的select语句 不会受到其他事物(不管其他事物有没有commit)的影响。

写:对一条记录而言,一个事物一旦update一条记录,其他事物只能等待这个事物commit才能update那条记录

举例并发分析:

比如表中num字段=10 需要根据num字段的数值做一些业务处理

事物A  begin   事物B begin  
select num 得到10   
根据结果10进行业务处理;  
处理完之后 num减一 update table set num = num-1;  
A 事物提交 commit; 此时num是9 此时A已经commit了
  select num 得到10 (此时的查询不受其它事物的影响)
  根据结果10进行业务处理;
  处理完之后 num减一  update table set num = num-1;
  会把num更新成8。
 结论: B以num是10的基础上 处理了众多逻辑,但是到update的时候 用到的b确是9 

 

表格中 update table set num = num-1;会受到其他commit事物的影响(B事物把num从9更新成了8) 而select不会(查到的还是10)。

利用乐观锁处理事物的并发

  数据库增加一个锁的处理列(版本号),查询的时候多查一个版本号, update的时候 where条件附加一个版本号条件并且更新时候并且把版本号+1,处理流程

  1)select num,version from table;

  2)update table set num=num-1 ,version =version+1 where condition=? version=#{version

  3)Query OK, 1 rows affected (0.04 sec) | 注意:1 rows affected 

 

     update的时候 where条件附加一个版本号条件并且更新时候并且把版本号+1: update table set num=num-1 ,version =version+1 where condition=? version=#{version} 

  如果出现了查询时候的版本号和where条件的版本号不一致 说明其他事物并发影响到了版本号 version,此时update语句的影响行数(Query OK, 1 rows affected (0.04 sec))是0 然后做异常处理。()

乐观锁处理并发的原理重点!

1)因为一个事物中的select语句不会不会收到其他事物的影响,也就是查不到其他事物的影响。所以两个事物共同执行时产生了并发的冲突。(innoDB引擎为了可重复读 保持一个事物的查询一致性)

2)虽然这个被并发的字段通过select查不出来,但是在where条件语句中 这个字段会受到其他事物的影响。所以可以利用这点 可以读到其他事物影响的数据 ,从而做出判断,防止并发。

文章开头也说了 对一条记录而言,一个事物一旦update一条记录,其他事物只能等待这个事物commit才能update那条记录。SO :只要在事物处理db的第一步 update这条记录,就可以防止并发了(即 悲观锁,自己领悟 不懂可以留下评论)

 

posted @ 2018-04-05 16:04 palapala 阅读(...) 评论(...) 编辑 收藏