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

来源:5-10 资金账户-账户转账-业务领域层的定义和编码实践

慕粉2045165721

2019-11-09

代码里面只体现了事务,从哪里看出是使用了乐观锁保证隔离性
图片描述

写回答

2回答

枫荇

2019-11-11

您好,同学!先看一下完整的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被额外扣减,如下表格:



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


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

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


这个方法本身没问题,但使用锁将执行串行化,增加了数据库负担降低了性能,这里的锁就是悲观锁,那么就采用乐观锁来解决问题,可以再看一下开头的那个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,如下几章课程


0
0

枫荇

2019-11-10

你好!同学!

这里乐观锁,是通过update语句实现的,代码在AccountDao中,“" and balance>=-1*CAST(? AS DECIMAL(30,6)) "”

//账户余额的更新

//amount 如果是负数,就是扣减;如果是正数,就是增加

func (dao *AccountDao) UpdateBalance(

accountNo string,

amount decimal.Decimal) (rows int64, err error) {

sql := "update account " +

" set balance=balance+CAST(? AS DECIMAL(30,6))" +

" where account_no=? " +

" and balance>=-1*CAST(? AS DECIMAL(30,6)) "

rs, err := dao.runner.Exec(sql,

amount.String(),

accountNo,

amount.String())

if err != nil {

return 0, err

}

return rs.RowsAffected()

}





0
2
枫荇
回复
慕粉2045165721
前往这里查看:http://coding.imooc.com/learn/questiondetail/qid/151175
2019-11-11
共2条回复

仿微信抢红包 Golang实战多版本抢红包系统

Golang红包系统单体版+并发版+分布式+微服务版,四大金装版、超值必修课

582 学习 · 159 问题

查看课程