表结构
1 | CREATE TABLE `user_balance` ( |
操作用户余额时注意
- 可重复读(记录扣费后余额快照)(select
coin后记录到user_balance_log表的coin_after) - 乐观锁(扣费冲突)(set
coin- 1000 wherecoin>= 1000) - 业务幂等(不同业务使用相应的订单表)
- 事务(用户余额表
user_balance、日志流水表user_balance_log、业务订单表绑定) - canal 监听 binlog 识别业务异常 (对比 binlog监听的
user_balance表coin变化量 和user_balance_log的coin记录总量 是否一致)
流水表只需要记录coin_after
事务过程
| 事务1 | 事务2 |
|---|---|
| BEGIN; | |
| BEGIN; | |
SELECT * FROM user_balance WHERE user_id = ‘kxw’; (coin=20000000) |
|
UPDATE user_balance SET coin= coin - 1000 WHERE user_id = ‘kxw’ AND coin >= 1000; |
|
SELECT * FROM user_balance WHERE user_id = ‘kxw’; (coin=20000000) |
|
UPDATE user_balance SET coin= coin - 1000 WHERE user_id = ‘kxw’ AND coin >= 1000; |
|
SELECT * FROM user_balance WHERE user_id = ‘kxw’; (coin=19999000) |
|
| COMMIT; | |
SELECT * FROM user_balance WHERE user_id = ‘kxw’; (coin=19998000) |
|
| COMMIT; |
- 流水表只需要记录
coin_after(变更后的余额)即可,因为变更前的余额,可能因为并发导致不准确,除非开启事务后,使用select for update来查询,而不是用普通的快照读








