并发修改账户余额不一致问题与解决方法悲观锁select…for update
问题描述:
a事务进行增加金额操作,需要操作account表 对余额balance进行加减 并生成操作明细account_operation_detail
a事务查询account 余额100 对余额进行进行加10
b事务查询account 余额100 对余额进行进行减10
由于a事务先结束b事务后结束,最终得到余额90元与期待的100不符合
解决方案
a,b事务开始时查询进行修改,增加悲观锁select…for update
select…for update锁详解
select…for update的作用就是:如果A事务中执行了select…for update,那么在其提交或回滚事务之前,B,C,D…事务是无法操作(写)A事务select…for update所命中的数据的!
bcd事务也无法再加上select…for update
增加悲观锁的效果
# 事务1:新建连接,执行sql如下BEGIN;
SELECT * FROM sys_user WHERE id = 1 FOR UPDATE;
-- commit;# 事务2:新建连接,执行同一个sql,结果会阻塞,需等待事务1释放锁BEGIN;
SELECT * FROM sys_user WHERE id = 1 FOR UPDATE;
commit;# 事务3:新建连接,执行sql,结果不会阻塞,事务1只对id=1的数据添加行锁BEGIN;
SELECT * FROM sys_user WHERE id = 3 FOR UPDATE;
commit;