其实这样理解是有问题的,mysql确实是有对单条的update语句默认加锁实现,但是只是仅仅的单条update。
比如UPDATE table1 SET num = num + 1 WHERE id=1;这样一条update语句,其实内部是分为两句,先查询到id = 1 的行的num值,再对num值进行更新,a = SELECT * FROM table1 WHERE id=1; UPDATE table1 SET num = a.num + 1 WHERE id=1;很显然,对num更新的操作进行了单条原子性的加锁,但是对id查询为1的操作并没有加锁。所以就会导致一个问题,在id = 1 查询完毕后,得到旧的num值,这时候另一个事务将num更新并提交。我们再对num进行更新,就会导致update的覆盖。所以如果不想发生这种情况就需要对前面id = 1的加共享锁或者是排他锁。
再者就是使用乐观锁,使用update t_goods set status=2,version=version+1 where id=#{id} and version=#{version}; 在更新的时候会去找当前的version值,如果一致则更新。a = select * from t_goods where id=#{id} and version=#{version} update t_goods set status=2,version=a.version+1 where id=#{id} and version=#{version};如果中途被改变,则第二条更新语句的version修改,无法更新。第一条查询语句只是查询到对应version的值用于对第二条修改语句的更新。。
我也在学, 希望我说的够清晰 , 所以是有加锁和乐观锁 两种方式保证并发的更新
@GG22G2 select1和update1的两个语句都是用一个where的,也就是说如果update1已经将version进行了修改,那update2的where将无法匹配,那么update2自然也无法执行。 比如最初version是1,根据update1进行了修改变了2。然后update2的语句就变成,update t_goods set status = 2,version = 1+1 where id=#{id} and version = 1(是最初的值,但是已经被update1进行修改成了2),所以update2会失败
我之前混淆了事务和锁的定义。
以mysql为例:在乐观锁中设置的是自动提交的,也就是一个语句就是一个事务,至于事务级别可能是提交读或是未提交读也是可以的。
基本步骤是:
1.查询出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根据商品信息生成订单
3.修改商品status为2
update t_goods
set status=2,version=version+1
where id=#{id} and version=#{version};
乐观锁中,上边的每一个语句就是一个小事务,select都是可以随便读的,只有在更新时检查。
不知道是不是我理解的这样???希望指正。。。