邀请码表设计必须带有效期和使用状态
直接用
CHAR(16)存邀请码,别用自增ID当邀请码——容易被枚举。字段至少包含:
code(唯一索引)、
inviter_id(发码用户ID)、
used_at(NULL表示未用)、
expires_at(DATETIME,建议默认 7 天后)、
created_at。避免把邀请关系硬编码进用户表,否则后期查谁邀请了谁、统计邀请数会非常慢。
注册时校验邀请码要原子性更新
不能先
SELECT再
UPDATE,否则并发注册可能让同一码被多人成功使用。必须用单条语句完成校验+标记已用:
UPDATE invite_codes SET used_at = NOW(), user_id = ? WHERE code = ? AND used_at IS NULL AND expires_at > NOW();
执行后检查
ROW_COUNT()是否为 1。返回 0 表示码无效(过期/已用/不存在),不是程序错误,而是业务规则拦截。
生成邀请码别用 UUID 或时间戳拼接
UUID 太长且可读性差;时间戳易预测。推荐用「随机字符串 + 校验位」组合:
用RAND()配合
CONV(FLOOR(RAND()*POW(36,6)),10,36)生成 6 位 base36 字符串(约 20 亿种组合) 插入前加
UNIQUE KEY(code)约束,冲突则重试(一般 1–2 次就成功) 避免字母
O和数字
0、
I和
1混淆,生成时过滤掉
邀请关系链不要靠递归查询实现
MySQL 8.0 虽支持 CTE 递归,但深度稍大(比如邀请 5 层以上)就会慢甚至超时。实际项目中,如果需要统计“某用户带来的全部下线”,应该在注册时就写死一级关系,并用定时任务或触发器维护一个
user_ancestors辅助表,存
user_id和其所有上级
inviter_id及层级。否则每次查都要
WITH RECURSIVE,线上扛不住。
