消费事务会产生 SQL 数据: SELECT * FROM `api_credits` WHERE `uid`='22' LIMIT 1 UPDATE `api_credits` SET `credits1`=`credits1`-'100' WHERE `uid`='22' AND `credits1`>='100' INSERT INTO `api_credits_log` SET `uid`='22', `cid`='3', `credits`='100', `balance`='79900', `time`='1701001020'
UPDATE `api_credits` SET `credits1`=`credits1`-'100' WHERE `uid`='22' AND `credits1`>='100' SELECT * FROM `api_credits` WHERE `uid`='22' LIMIT 1 INSERT INTO `api_credits_log` SET `uid`='22', `cid`='3', `credits`='100', `balance`='79900', `time`='1701001020'
@coderxy 不是单用户,在当前系统,这个用户 ID 是 22 ,可以在用户它的系统,可能它的用户有很多,他们要操作积分变动都是走的 22 这个用户的总积分。
looo
2023-12-05 11:05:22 +08:00
1. 你这个查询:SELECT * FROM `api_credits` WHERE `uid`='22' LIMIT 1 肯定要限制住拿到的是没有更新过的,可以采用数据库行锁:SELECT * FROM `api_credits` WHERE `uid`='22' LIMIT 1 FOR UPDATE; 记得加要加事务。
2. 建议你以后更新数据有并发的,可以增加 WHERE 条件,条件就是更新的值必须是你查询出来的值,然后在去 SET 更新。
looo
2023-12-05 11:11:18 +08:00
MySQL 默认存储引擎( InnoDB ) UPDATE 会默认加行锁🔐,有时候巧妙的去利用 UPDATE 来避免资源竞争。
cxk0
2023-12-05 11:11:37 +08:00
如果仅有增加不会减少,类似等级,可以用记录消化; 如果是有增有减,SQL 级别的 select for update;