0

0

mysql如何实现积分系统设计_mysql业务项目解析

P粉602998670

P粉602998670

发布时间:2026-01-05 09:02:02

|

871人浏览过

|

来源于php中文网

原创

积分变更必须用事务包裹并配合乐观锁,流水表需含trace_id、前后余额等字段,Redis缓存余额并异步双写,过期清理须分批避峰。

mysql如何实现积分系统设计_mysql业务项目解析

积分增减必须用事务包裹,否则并发写入会丢分

用户做签到、下单、评价等行为时,积分变动常伴随其他业务操作(如更新订单状态)。若不加事务,高并发下 SELECT ... FOR UPDATE 缺失或 UPDATE 未隔离,会出现超发或漏扣。比如两个线程同时读取用户当前积分为 100,各自加 10 后写回 110,实际应为 120。

  • 所有积分变更操作必须在 BEGIN TRANSACTION 内完成,且事务粒度尽量小
  • 优先使用 UPDATE user_points SET points = points + ? WHERE user_id = ? AND version = ? 配合乐观锁(version 字段),比悲观锁更轻量
  • 避免先 SELECTUPDATE 的两步写法;如必须查后改,务必加 SELECT ... FOR UPDATE 且确保走主键或唯一索引
  • 注意 MySQL 默认隔离级别是 REPEATABLE READ,但无法防止“幻读”场景下的计数偏差,积分流水表插入和余额更新需在同一事务中完成

积分流水表要带业务单号+类型+幂等键,不可只存净变化

单纯记录“+10 分”无法追溯来源,也无法对账或回滚。每条积分变动必须对应一次明确的业务动作,并支持重放与校验。

  • point_log 表至少包含:id(自增)、user_idorder_no(如订单号/活动ID)、type(枚举:sign_in、order_pay、refund、admin_adjust)、amount(正负整数)、before_balanceafter_balancetrace_id(全局幂等键)
  • trace_id 必须由上游业务生成并保证唯一(如 order_pay_20240520123456789),插入前用 INSERT ... ON DUPLICATE KEY UPDATE 防重
  • 不要省略 before_balanceafter_balance —— 它们是核对最终余额是否一致的关键依据,排查问题时比翻日志快得多
CREATE TABLE point_log (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_id BIGINT NOT NULL,
  order_no VARCHAR(64) DEFAULT '',
  type TINYINT NOT NULL COMMENT '1=签到,2=支付,3=退款,4=后台调整',
  amount INT NOT NULL,
  before_balance INT NOT NULL,
  after_balance INT NOT NULL,
  trace_id VARCHAR(128) NOT NULL UNIQUE,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_user_created (user_id, created_at),
  INDEX idx_trace (trace_id)
) ENGINE=InnoDB;

余额查询不能直连主库,要用缓存兜底+异步双写

用户首页频繁查积分,若每次都查 user_points 表,主库压力大,且一旦慢查询拖垮连接池,整个登录链路都会卡住。

AI Web Designer
AI Web Designer

AI网页设计师,快速生成个性化的网站设计

下载
  • 用户积分余额必须写入 Redis,结构用 hash:键为 user:points:{user_id},字段为 balanceversion
  • 每次积分变更后,MySQL 更新成功 → 异步发 MQ 消息 → 消费端更新 Redis;Redis 更新失败要告警,但**不阻塞主流程**
  • 前端查积分时,优先读 Redis;若 Redis 为空或异常,则降级查 MySQL 并回填缓存(注意加锁防击穿)
  • 禁止在事务中同步调用 Redis 写操作 —— 网络延迟或 Redis 故障会导致事务长时间挂起甚至超时

过期积分要分批清理,别用 DELETE FROM ... WHERE expired_at < NOW()

全表扫描删过期积分,锁表时间长、IO 压力大,高峰期可能直接拖垮主库。

  • 按月分表存储过期规则(如 point_expired_202404),或在流水表加 expired_at 字段并建联合索引 (user_id, expired_at)
  • 用游标分页清理:DELETE FROM point_log WHERE id < ? AND expired_at < NOW() ORDER BY id DESC LIMIT 1000,每次取最大 id 作为下次起点
  • 清理任务必须避开业务高峰,并监控 Rows_affected 和执行耗时;单次超过 2 秒应暂停几秒再继续
  • 过期逻辑建议放在应用层判断(如查余额时过滤已过期部分),数据库只做物理归档,不参与实时计算
真实项目里最常被忽略的是流水表的 trace_id 设计和 Redis 回填时的并发竞争——这两处出问题,基本意味着积分对不上,而且很难定位。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

686

2023.06.20

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

514

2023.06.21

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

287

2023.07.18

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

519

2023.07.19

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

267

2023.07.25

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

392

2023.08.08

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

542

2023.08.11

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

668

2023.08.14

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.5万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 850人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号