请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

5-10章节乐观锁体现在哪里

原问题是这个:https://coding.imooc.com/learn/questiondetail/150936.html
老师,这里的cast是转换函数。
balance>=-1*amount是什么意思?这条语句怎么能体现乐观锁?
乐观锁不是有Version字段来检查是否有更新吗

正在回答

2回答

枫荇 2019-11-11 18:34:26

您好,同学!先看一下完整的SQL语句

update account set balance=balance+CAST(? AS DECIMAL(30,6)) where account_no=? and balance>=-1*CAST(? AS DECIMAL(30,6)) 


通常我们更新数据库的时候是这样执行的:

1. 开启一个数据库事务。

2. 查询出需要更新的数据

select account_no,balance from account where account_no=? 

3. 计算新的balance值:

balance=balance-扣减金额

4. 执行更新语句

update account set balance=? where account_no=? 

5. 提交事务。


只需要指定需要更新的数据和数据库表唯一标识字段更新即可,那么这样带来的问题就是在高并发情况下运行时,会导致balance被额外扣减,如下表格:


https://img1.sycdn.imooc.com/szimg/5dc9358b094f4b3d10040396.jpg


从表格中可以看到,更新后的balance和预期不一样,并发问题导致剩余金额错误,那其中一种解决方法是使用数据库行锁,也就是把上面的第2步修改一下,添加for update:


select account_no,balance from account where account_no=?  for update

那么只有拿到锁的事务才可以执行,就把2个事务强制串行化,那么剩余金额就不会出现错误了,过程就变成了:

https://img1.sycdn.imooc.com/szimg/5dc936fa09c5794615660660.jpg


这个方法本身没问题,但使用锁将执行串行化,增加了数据库负担降低了性能,这里的锁就是悲观锁,那么就采用乐观锁来解决问题,可以再看一下开头的那个SQL:

update account set balance=balance+ 扣减的值 where account_no=? and balance>=-1*扣减的值

目的是扣减的计算逻辑从代码移动到update语句吗,update语句执行时数据库本身会保证原子性,

同时,在where语句中除了执行唯一标识,还加了一个限制 and balance>=-1*扣减的值,含义就是,如果更新的数据中如果 balance>=-1*扣减的值,剩余金额大于扣减金额,才可以扣减;如果剩余金额小于扣减金额,就无法扣减,update语句也就会不会实际执行了。

至于cast函数,是把传进来的数字转换成对应的数据库表字段类型,才能正确执行,所以最终的只需要执行一个update SQL就可以了:


update account set balance=balance+CAST(? AS DECIMAL(30,6)) where account_no=? and balance>=-1*CAST(? AS DECIMAL(30,6)) 


另外同学可以异步学习另外的免费课程来巩固这一块的认知:

https://www.imooc.com/learn/1101,如下几章课程

https://img1.sycdn.imooc.com//szimg/5dc939060965e69315340764.jpg

0 回复 有任何疑惑可以回复我~
枫荇 2019-11-11 18:35:47

这里的balance充当了version字段同样的语义,乐观锁不一定必须使用version字段。

0 回复 有任何疑惑可以回复我~

相似问题

登录后可查看更多问答,登录/注册

问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信