public function cash(): Response
{
$param = postMore([
['member_id',1],
['phone',1],
['money',30],
['back_card',1],
['create_time',time()]
]);
Db::startTrans();
try {
$this->member($param);
$this->model->save($this->datatable,$param);
Db::commit();
} catch (Throwable $e) {
Db::rollback();
$this->error($e->getMessage(),$e->getCode());
}
return $this->success();
}
/**
* 判断用户余额是否足够
* 修改用户余额和提现中金额
* @throws MyBusinessException
*/
public function member($param)
{
$member = $this->model->findOne('back_member',['id' => $param['member_id']],'balance,txz_profit');
if ($member['balance'] < $param['money']) {
$this->error('用户余额不足',30001);
}
$member_data = [
'balance' => bcsub($member['balance'],$param['money'], 2),//余额
'txz_profit' => bcadd($param['money'], $member['txz_profit'], 2),//提现中金额
];
$this->model->upd('back_member',['id' => $param['member_id']],$member_data);
}
用户提现时,修改用户余额和提现中金额,然后增加一条提现记录。目前问题在于高并发多进程的情况下,提现记录增加了,但是修改用户余额的时候,数据可能并不是最新的。
目前测试改为单进程是没有这么问题。然后想问一下大佬有没有办法让这个请求始终在同一个进程中
目前解决办法是改为单进程,或者使用
文件锁来控制始终在同一个经常中,
因为你读取和写入是两步操作,不是原子操作,所以会有并发问题。用一个SQL就行了,一个SQL它是原子操作。
SQL类似
update member set balance = balance - $value where member_id = x and balance >= $value
。返回影响的行数为1代表成功,为0代表余额不足,这样不会有问题。
或者更改数据库事务隔离级别为序列化,这样即使你分成两步,数据库事务也是串行,不会有并发问题。
感谢,我一会试一下