会员基础表必须包含哪些字段
核心是区分「身份」和「状态」:身份靠
user_id(主键,推荐 BIGINT AUTO_INCREMENT 或 UUID),状态靠
status(TINYINT,如 0=禁用、1=正常、2=待验证)。别用
is_deleted软删除代替状态字段——它和「封号」「冻结」「未激活」语义不同,混用会导致查询逻辑混乱。
必须有的字段包括:
mobile(唯一索引,用于登录/找回)、
password_hash(不是 password!)、
created_at、
updated_at。别存明文密码,别用
md5(),用
bcrypt或 MySQL 8.0+ 的
VALIDATE_PASSWORD配合应用层哈希。
常见错误:把微信 openid、unionid 直接塞进主表。应该拆到
user_auths关联表,支持同一用户多平台登录。
等级与权益要分开建表,别用 JSON 存规则
会员等级(如青铜、黄金、VIP)是有限且需频繁 JOIN 查询的维度,适合独立表
member_levels,含
level_id、
name、
min_points、
max_points。用户当前等级存在
users.level_id,并加索引。
权益(如免运费、专属客服、折扣率)是组合式、可配置的,应建
member_privileges+
user_privilege_grants两张表。避免用
JSON字段存权益列表——查「所有有免运费权限的用户」时无法走索引,也难做变更审计。
示例场景:运营临时给 VIP 用户加「生日双倍积分」权益,只需往
user_privilege_grants插一条记录,不影响等级计算逻辑。
积分、余额、优惠券必须分库分表或至少分表
这三类数据写入高频、一致性要求高、且业务逻辑隔离性强。合并在
users表里会导致锁表风险上升,特别是大促期间。
user_points:记录总积分、冻结积分、来源明细(用另一张
point_logs记流水)
user_balances:余额、可用余额、冻结余额,每次变更必须带
version或用 SELECT FOR UPDATE 防超扣
coupons+
user_coupons:优惠券模板和用户持有关系分离,过期、核销状态在
user_coupons.status控制
别在
users表里加
points、
balance字段——初期省事,半年后慢查询和事务冲突会集中爆发。
MySQL 8.0+ 推荐开启这些配置
不是功能开关,而是防坑底线:
sql_mode必须包含
STRICT_TRANS_TABLES,否则
INSERT INTO users (mobile) VALUES ('') 会静默转成 '0',导致手机号丢失;
explicit_defaults_for_timestamp=ON避免
created_at在某些 INSERT 场景下被意外设为 '0000-00-00 00:00:00';
innodb_strict_mode=ON让外键、行格式异常立刻报错,不埋雷。
还有个容易被忽略的点:所有时间字段统一用
TIMESTAMP(自动时区转换)或统一用
DATETIME(无时区),别混用。尤其当应用部署在多个时区,又用
NOW()和
SYSDATE()混插时,数据对不上根本没法 debug。
