下面继续整理成可以直接给后端开发、数据库设计和技术评审使用的《数据库 ER + 字段设计文档》。重点把 用户、会员等级、推荐关系、升级审核、商品、SKU、购物车、地址、订单、支付、积分、转账、提现、收藏、关注、浏览记录、审计日志 统一起来,同时明确主键、唯一约束、索引和状态字段。
会员推荐关系 + 新零售商城
数据库 ER + 字段设计文档
版本: V1.0
数据库建议: MySQL 8.0+
字符集: utf8mb4
排序规则建议: utf8mb4_0900_ai_ci
主键策略: BIGINT UNSIGNED / 雪花 ID 或数据库自增 ID
金额存储: BIGINT,单位“分”
积分存储: BIGINT,整数
时间: DATETIME / TIMESTAMP,建议统一 UTC 存储
软删除: 业务数据按需增加 deleted_at
1. 数据库总体设计
系统按业务域拆分:
数据库
│
├── 用户域
│ ├── users
│ ├── user_profiles
│ ├── user_identities
│ └── user_bank_accounts
│
├── 会员域
│ ├── member_levels
│ ├── members
│ ├── member_relations
│ ├── member_upgrade_requests
│ └── member_upgrade_logs
│
├── 商城域
│ ├── categories
│ ├── zones
│ ├── products
│ ├── product_skus
│ ├── product_images
│ ├── carts
│ └── cart_items
│
├── 交易域
│ ├── addresses
│ ├── orders
│ ├── order_items
│ ├── payments
│ └── order_logs
│
├── 资产域
│ ├── point_accounts
│ ├── point_transactions
│ ├── point_transfers
│ ├── withdrawal_requests
│ └── withdrawal_logs
│
├── 用户行为域
│ ├── favorites
│ ├── follows
│ └── browsing_histories
│
└── 系统域
├── announcements
├── service_configs
└── audit_logs2. ER 总体关系
核心关系:
┌──────────────┐
│ users │
│ 用户主表 │
└──────┬───────┘
│
┌─────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌────────────────┐ ┌───────────────┐ ┌──────────────┐
│ user_profiles │ │ members │ │ point_accounts│
│ 用户资料 │ │ 会员 │ │ 积分账户 │
└────────────────┘ └───────┬───────┘ └──────┬───────┘
│ │
┌────────────┼───────┐ │
│ │ │ │
▼ ▼ ▼ ▼
member_levels relations upgrade transactions
requests
│
▼
upgrade_logs
users
│
├─────────────── addresses
│
├─────────────── orders
│ │
│ ├──── order_items
│ └──── payments
│
├─────────────── carts
│ │
│ └──── cart_items
│
├─────────────── favorites ───── products
├─────────────── follows
└─────────────── browsing_histories ───── products
products
│
├──── categories
├──── zones
├──── product_images
└──── product_skus
point_accounts
│
├──── point_transactions
└──── point_transfers
users
├──── user_identities
├──── user_bank_accounts
└──── withdrawal_requests3. 核心设计原则
3.1 用户与会员分离
不要把所有会员字段全部塞进 users。
推荐:
users
↓
members
↓
member_levels原因:
用户身份:
登录、手机号、密码、状态会员身份:
会员等级、会员状态、升级属于不同业务域。
4. users 用户主表
表名:
users用途:
保存系统所有用户的基础身份。
| 字段 | 类型 | NULL | 默认值 | 说明 |
|---|---|---|---|---|
| id | BIGINT UNSIGNED | 否 | - | 用户 ID,PK |
| mobile | VARCHAR(20) | 否 | - | 手机号 |
| password_hash | VARCHAR(255) | 否 | - | 密码哈希 |
| status | TINYINT | 否 | 1 | 账号状态 |
| last_login_at | DATETIME | 是 | NULL | 最近登录时间 |
| last_login_ip | VARCHAR(45) | 是 | NULL | 最近登录 IP |
| created_at | DATETIME | 否 | CURRENT | 创建时间 |
| updated_at | DATETIME | 否 | CURRENT | 更新时间 |
| deleted_at | DATETIME | 是 | NULL | 软删除 |
status
0 = 禁用
1 = 正常
2 = 锁定索引
PRIMARY KEY (id)
UNIQUE KEY uk_mobile (mobile)
KEY idx_status_created (status, created_at)5. user_profiles 用户资料表
表名:
user_profiles用途:
保存非认证型资料。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 ID |
| real_name | VARCHAR(50) | 姓名 |
| nickname | VARCHAR(50) | 昵称 |
| avatar_url | VARCHAR(500) | 头像 |
| VARCHAR(100) | 微信号 | |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
约束:
UNIQUE KEY uk_user (user_id)6. user_identities 实名信息表
表名:
user_identities用途:
管理实名资料。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| real_name | VARCHAR(100) | 实名姓名 |
| id_card_no_encrypted | VARBINARY / TEXT | 加密身份证号 |
| id_card_last4 | CHAR(4) | 后四位 |
| status | TINYINT | 认证状态 |
| verified_at | DATETIME | 认证时间 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
状态:
0 = 未认证
1 = 审核中
2 = 已认证
3 = 认证失败安全
身份证号不得明文存储。
推荐:
原始值 → 应用层加密 → 数据库存储7. user_bank_accounts 银行账户表
表名:
user_bank_accounts用途:
提现银行卡资料。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| bank_name | VARCHAR(100) | 银行名称 |
| card_no_encrypted | VARBINARY / TEXT | 加密银行卡号 |
| card_last4 | CHAR(4) | 尾号 |
| holder_name | VARCHAR(100) | 持卡人 |
| status | TINYINT | 状态 |
| is_default | TINYINT | 默认银行卡 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
约束:
KEY idx_user_status (user_id, status)银行卡号不得明文返回接口。
8. member_levels 会员等级表
表名:
member_levels用途:
定义会员等级。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| name | VARCHAR(50) | 等级名称 |
| code | VARCHAR(50) | 等级编码 |
| sort | INT | 等级顺序 |
| description | TEXT | 等级说明 |
| upgrade_enabled | TINYINT | 是否允许升级 |
| status | TINYINT | 状态 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
例如:
1 一星会员
2 二星会员
3 三星会员约束:
UNIQUE KEY uk_code (code)
UNIQUE KEY uk_sort (sort)9. members 会员表
表名:
members用途:
记录用户当前会员身份。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| level_id | BIGINT | 当前等级 |
| status | TINYINT | 会员状态 |
| joined_at | DATETIME | 成为会员时间 |
| upgraded_at | DATETIME | 最近升级时间 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
约束:
UNIQUE KEY uk_user (user_id)
KEY idx_level (level_id)10. member_relations 推荐关系表
表名:
member_relations这是整个推荐体系的核心表。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| parent_user_id | BIGINT | 推荐人 |
| child_user_id | BIGINT | 被推荐人 |
| relation_level | INT | 推荐层级 |
| status | TINYINT | 状态 |
| created_at | DATETIME | 建立时间 |
例如:
A 推荐 B记录:
parent_user_id = A
child_user_id = B
relation_level = 1如果未来支持多层团队:
A → B → C可以产生:
A → B level 1
B → C level 1
A → C level 2约束
UNIQUE KEY uk_parent_child (parent_user_id, child_user_id)
KEY idx_parent_level (
parent_user_id,
relation_level,
status
)
KEY idx_child (
child_user_id
)禁止:
parent_user_id = child_user_id11. 推荐关系为什么不建议直接放 users.referrer_id
简单系统可以:
users.referrer_id但本项目未来存在:
团队
多层级
统计
团队人数
关系查询因此建议使用独立关系表。
如果为了查询效率,也可以在 users 增加:
direct_referrer_id作为冗余字段。
但:
users.direct_referrer_id和:
member_relations必须由服务端事务保持一致。
12. member_upgrade_requests 升级申请表
表名:
member_upgrade_requests| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| request_no | VARCHAR(50) | 申请单号 |
| user_id | BIGINT | 申请用户 |
| from_level_id | BIGINT | 当前等级 |
| to_level_id | BIGINT | 申请等级 |
| status | VARCHAR(30) | 状态 |
| applicant_remark | TEXT | 申请说明 |
| reviewer_id | BIGINT | 审核人 |
| reviewer_remark | TEXT | 审核说明 |
| created_at | DATETIME | 申请时间 |
| reviewed_at | DATETIME | 审核时间 |
| updated_at | DATETIME | 更新时间 |
状态:
pending
approved
rejected
cancelled约束
同一个用户不能同时存在两个 pending。
实现方式:
可以通过应用层 + 唯一约束设计。
例如增加:
pending_flag然后建立:
UNIQUE(user_id, pending_flag)其中只有待审核状态使用固定值。
13. member_upgrade_logs 审核日志表
表名:
member_upgrade_logs用途:
记录升级状态历史。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| request_id | BIGINT | 升级申请 |
| operator_id | BIGINT | 操作人 |
| action | VARCHAR(30) | 操作 |
| from_status | VARCHAR(30) | 原状态 |
| to_status | VARCHAR(30) | 新状态 |
| remark | TEXT | 说明 |
| ip | VARCHAR(45) | IP |
| user_agent | VARCHAR(500) | UA |
| created_at | DATETIME | 时间 |
例如:
pending → approved记录:
operator_id
from_status = pending
to_status = approved
action = approve14. categories 商品分类表
表名:
categories| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| parent_id | BIGINT | 上级分类 |
| name | VARCHAR(100) | 名称 |
| icon | VARCHAR(500) | 图标 |
| sort | INT | 排序 |
| status | TINYINT | 状态 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
支持:
一级分类
└── 二级分类索引:
KEY idx_parent_status (parent_id, status)15. zones 商品专区表
表名:
zones用途:
新品、热销、专题等运营专区。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| name | VARCHAR(100) | 专区名称 |
| cover | VARCHAR(500) | 封面 |
| description | TEXT | 描述 |
| sort | INT | 排序 |
| status | TINYINT | 状态 |
| start_at | DATETIME | 开始时间 |
| end_at | DATETIME | 结束时间 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
16. zone_products 专区商品关联表
表名:
zone_products因为一个商品可以属于多个专区,所以建立中间表。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| zone_id | BIGINT | 专区 |
| product_id | BIGINT | 商品 |
| sort | INT | 排序 |
| created_at | DATETIME | 创建时间 |
约束:
UNIQUE(zone_id, product_id)17. products 商品主表
表名:
products| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| category_id | BIGINT | 分类 |
| name | VARCHAR(255) | 商品名称 |
| subtitle | VARCHAR(255) | 副标题 |
| cover_url | VARCHAR(500) | 主图 |
| description | LONGTEXT | 商品详情 |
| price_cent | BIGINT | 基础价格,分 |
| original_price_cent | BIGINT | 原价,分 |
| stock | BIGINT | 总库存 |
| sales_count | BIGINT | 销量 |
| status | TINYINT | 上下架 |
| sort | INT | 排序 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
状态:
0 = 下架
1 = 上架
2 = 草稿18. product_skus 商品 SKU 表
表名:
product_skus| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| product_id | BIGINT | 商品 |
| sku_code | VARCHAR(100) | SKU 编码 |
| name | VARCHAR(255) | SKU 名称 |
| spec_json | JSON | 规格 |
| price_cent | BIGINT | SKU 售价 |
| original_price_cent | BIGINT | SKU 原价 |
| stock | BIGINT | 库存 |
| locked_stock | BIGINT | 锁定库存 |
| status | TINYINT | 状态 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
库存设计:
可售库存 = stock - locked_stock也可以直接使用:
available_stock但二者不要重复维护,避免数据不一致。
19. product_images 商品图片表
表名:
product_images| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| product_id | BIGINT | 商品 |
| url | VARCHAR(500) | 图片 |
| type | VARCHAR(30) | 类型 |
| sort | INT | 排序 |
| created_at | DATETIME | 创建时间 |
类型:
cover
gallery
detail20. carts 购物车主表
表名:
carts如果每个用户只有一个购物车,可以非常简单:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
约束:
UNIQUE(user_id)21. cart_items 购物车商品表
表名:
cart_items| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| cart_id | BIGINT | 购物车 |
| product_id | BIGINT | 商品 |
| sku_id | BIGINT | SKU |
| quantity | INT | 数量 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
约束:
UNIQUE(cart_id, sku_id)加入同一 SKU 时:
quantity += new_quantity而不是产生重复购物车记录。
22. addresses 收货地址表
表名:
addresses| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| receiver | VARCHAR(50) | 收货人 |
| mobile | VARCHAR(20) | 手机 |
| province | VARCHAR(50) | 省 |
| city | VARCHAR(50) | 市 |
| district | VARCHAR(50) | 区 |
| detail | VARCHAR(255) | 详细地址 |
| is_default | TINYINT | 默认 |
| created_at | DATETIME | 创建 |
| updated_at | DATETIME | 更新 |
索引:
KEY idx_user_default (user_id, is_default)建议保证每个用户最多一个默认地址。
23. orders 订单主表
表名:
orders这是商城交易核心表。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| order_no | VARCHAR(50) | 订单号 |
| user_id | BIGINT | 用户 |
| status | VARCHAR(30) | 订单状态 |
| product_amount_cent | BIGINT | 商品金额 |
| discount_amount_cent | BIGINT | 优惠金额 |
| freight_amount_cent | BIGINT | 运费 |
| points_discount_cent | BIGINT | 积分抵扣金额 |
| payable_amount_cent | BIGINT | 应付金额 |
| paid_amount_cent | BIGINT | 实付金额 |
| used_points | BIGINT | 使用积分 |
| receiver_snapshot | JSON | 收货地址快照 |
| remark | VARCHAR(500) | 备注 |
| created_at | DATETIME | 创建 |
| paid_at | DATETIME | 支付 |
| shipped_at | DATETIME | 发货 |
| completed_at | DATETIME | 完成 |
| cancelled_at | DATETIME | 取消 |
| updated_at | DATETIME | 更新 |
订单状态
pending_payment
pending_shipment
shipped
completed
cancelled
refund可以根据实际业务增加:
refunding
refunded订单号
UNIQUE(order_no)24. 为什么订单必须保存快照
订单不能只存:
product_id因为之后商品可能:
改名
改价
下架
删除
修改规格所以订单商品必须保存:
商品名称
SKU 名称
价格
规格
图片25. order_items 订单商品表
表名:
order_items| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| order_id | BIGINT | 订单 |
| product_id | BIGINT | 原商品 ID |
| sku_id | BIGINT | 原 SKU ID |
| product_name | VARCHAR(255) | 商品名称快照 |
| sku_name | VARCHAR(255) | SKU 快照 |
| sku_spec_json | JSON | 规格快照 |
| cover_url | VARCHAR(500) | 图片快照 |
| price_cent | BIGINT | 成交单价 |
| quantity | INT | 数量 |
| subtotal_cent | BIGINT | 小计 |
| created_at | DATETIME | 创建时间 |
索引:
KEY idx_order (order_id)26. payments 支付表
表名:
payments| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| payment_no | VARCHAR(50) | 支付单号 |
| order_id | BIGINT | 订单 |
| user_id | BIGINT | 用户 |
| provider | VARCHAR(30) | 支付渠道 |
| method | VARCHAR(30) | 支付方式 |
| amount_cent | BIGINT | 支付金额 |
| status | VARCHAR(30) | 支付状态 |
| provider_trade_no | VARCHAR(100) | 第三方交易号 |
| paid_at | DATETIME | 支付时间 |
| callback_at | DATETIME | 回调时间 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
状态:
pending
paid
failed
cancelled
refunded约束:
UNIQUE(payment_no)
KEY idx_order_status(order_id, status)
UNIQUE(provider, provider_trade_no)第三方交易号需要允许 NULL。
27. order_logs 订单状态日志
表名:
order_logs| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| order_id | BIGINT | 订单 |
| operator_type | VARCHAR(30) | 操作主体 |
| operator_id | BIGINT | 操作人 |
| action | VARCHAR(50) | 动作 |
| from_status | VARCHAR(30) | 原状态 |
| to_status | VARCHAR(30) | 新状态 |
| remark | TEXT | 说明 |
| created_at | DATETIME | 时间 |
operator_type:
user
admin
system
payment
merchant28. point_accounts 积分账户表
表名:
point_accounts| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| available_points | BIGINT | 可用积分 |
| frozen_points | BIGINT | 冻结积分 |
| version | BIGINT | 乐观锁版本 |
| updated_at | DATETIME | 更新时间 |
| created_at | DATETIME | 创建 |
约束:
UNIQUE(user_id)29. point_transactions 积分流水表
表名:
point_transactions这是积分系统最重要的账本表。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| transaction_no | VARCHAR(50) | 流水号 |
| user_id | BIGINT | 用户 |
| type | VARCHAR(30) | 类型 |
| amount | BIGINT | 变动积分 |
| balance_before | BIGINT | 变动前 |
| balance_after | BIGINT | 变动后 |
| reference_type | VARCHAR(50) | 业务类型 |
| reference_id | BIGINT | 业务 ID |
| remark | VARCHAR(500) | 备注 |
| created_at | DATETIME | 创建时间 |
类型:
recharge
reward
transfer_in
transfer_out
order_use
withdraw
freeze
unfreeze
adjustment约束:
UNIQUE(transaction_no)建议增加:
UNIQUE(reference_type, reference_id, user_id, type)但具体唯一规则需要根据业务场景调整。
30. point_transfers 积分转账记录
表名:
point_transfers用于记录一次完整的 A → B 转账。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| transfer_no | VARCHAR(50) | 转账单号 |
| sender_user_id | BIGINT | 转出用户 |
| receiver_user_id | BIGINT | 接收用户 |
| points | BIGINT | 转账积分 |
| status | VARCHAR(30) | 状态 |
| sender_transaction_id | BIGINT | 转出流水 |
| receiver_transaction_id | BIGINT | 转入流水 |
| created_at | DATETIME | 创建 |
| completed_at | DATETIME | 完成 |
状态:
pending
completed
failed
cancelled约束:
UNIQUE(transfer_no)31. 积分转账数据库事务
完整转账:
BEGIN
锁定发送者 point_accounts
↓
锁定接收者 point_accounts
↓
检查发送方余额
↓
扣减发送方
↓
增加接收方
↓
写 sender point_transaction
↓
写 receiver point_transaction
↓
更新 point_transfer
↓
COMMIT不能只:
UPDATE point_accounts而不生成流水。
32. withdrawal_requests 提现申请表
表名:
withdrawal_requests| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| withdrawal_no | VARCHAR(50) | 提现单号 |
| user_id | BIGINT | 用户 |
| points | BIGINT | 提现积分 |
| amount_cent | BIGINT | 提现金额 |
| bank_account_id | BIGINT | 银行账户 |
| status | VARCHAR(30) | 状态 |
| reviewer_id | BIGINT | 审核人 |
| reviewer_remark | TEXT | 审核备注 |
| paid_at | DATETIME | 打款时间 |
| created_at | DATETIME | 创建 |
| updated_at | DATETIME | 更新 |
状态:
pending
reviewing
approved
rejected
paid
cancelled33. 提现银行卡快照
提现不能只依赖:
bank_account_id因为用户后续可能修改银行卡。
建议同时保存:
bank_name_snapshot
holder_name_snapshot
card_last4_snapshot例如:
| 字段 | 类型 |
|---|---|
| bank_name_snapshot | VARCHAR(100) |
| holder_name_snapshot | VARCHAR(100) |
| card_last4_snapshot | CHAR(4) |
这样历史提现记录仍然能够保持当时状态。
34. withdrawal_logs 提现状态日志
表名:
withdrawal_logs| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| withdrawal_id | BIGINT | 提现单 |
| operator_id | BIGINT | 操作人 |
| action | VARCHAR(50) | 操作 |
| from_status | VARCHAR(30) | 原状态 |
| to_status | VARCHAR(30) | 新状态 |
| remark | TEXT | 说明 |
| created_at | DATETIME | 时间 |
35. favorites 收藏表
表名:
favorites| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| product_id | BIGINT | 商品 |
| created_at | DATETIME | 收藏时间 |
约束:
UNIQUE(user_id, product_id)防止重复收藏。
36. follows 关注表
表名:
follows因为当前系统无法完全确认“关注”的具体业务对象,因此设计为通用结构。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| target_type | VARCHAR(30) | 对象类型 |
| target_id | BIGINT | 对象 ID |
| created_at | DATETIME | 时间 |
例如:
shop
brand
product
zone约束:
UNIQUE(user_id, target_type, target_id)37. browsing_histories 浏览记录表
表名:
browsing_histories| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 用户 |
| product_id | BIGINT | 商品 |
| browse_count | INT | 浏览次数 |
| first_browsed_at | DATETIME | 首次时间 |
| last_browsed_at | DATETIME | 最近时间 |
约束:
UNIQUE(user_id, product_id)每次浏览:
browse_count += 1
last_browsed_at = NOW()不需要每次都新增一条完全重复记录。
38. announcements 公告表
表名:
announcements| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| title | VARCHAR(255) | 标题 |
| content | LONGTEXT | 内容 |
| is_top | TINYINT | 置顶 |
| status | TINYINT | 状态 |
| start_at | DATETIME | 开始 |
| end_at | DATETIME | 结束 |
| created_at | DATETIME | 创建 |
| updated_at | DATETIME | 更新 |
39. audit_logs 审计日志表
表名:
audit_logs整个系统的统一操作审计表。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| user_id | BIGINT | 操作用户 |
| action | VARCHAR(100) | 操作 |
| resource_type | VARCHAR(50) | 资源类型 |
| resource_id | BIGINT | 资源 ID |
| request_id | VARCHAR(100) | 请求 ID |
| method | VARCHAR(20) | HTTP 方法 |
| path | VARCHAR(500) | 接口 |
| ip | VARCHAR(45) | IP |
| user_agent | VARCHAR(500) | UA |
| result | VARCHAR(30) | 结果 |
| detail_json | JSON | 详情 |
| created_at | DATETIME | 时间 |
敏感数据不要直接写进 detail_json。
40. 服务配置表
表名:
service_configs| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | PK |
| config_key | VARCHAR(100) | 配置键 |
| config_value | TEXT | 配置值 |
| description | VARCHAR(255) | 说明 |
| status | TINYINT | 状态 |
| updated_at | DATETIME | 更新时间 |
例如:
points.exchange_rate = 100
withdraw.enabled = 1
mall.enabled = 1敏感密钥不能放在该表以明文保存。
41. 关键 ER 关系
用户与会员
users 1 ───── 1 members
members N ───── 1 member_levels推荐关系
users 1 ───── N member_relations
users 1 ───── N member_relations逻辑上:
parent_user_id → child_user_id升级
users 1 ───── N member_upgrade_requests
member_upgrade_requests
│
├── from_level_id → member_levels
├── to_level_id → member_levels
└── 1 ───── N member_upgrade_logs商品
categories 1 ───── N products
products 1 ───── N product_skus
products 1 ───── N product_images
zones N ───── N products
↓
zone_products购物车
users 1 ───── 1 carts
carts 1 ───── N cart_items
cart_items N ───── 1 product_skus订单
users 1 ───── N orders
orders 1 ───── N order_items
orders 1 ───── N payments
orders 1 ───── N order_logs积分
users 1 ───── 1 point_accounts
point_accounts 1 ───── N point_transactions
users
└──── N point_transfers
├── sender_user_id
└── receiver_user_id提现
users 1 ───── N withdrawal_requests
withdrawal_requests N ───── 1 user_bank_accounts
withdrawal_requests 1 ───── N withdrawal_logs42. 数据库核心索引汇总
重点索引:
users
├── uk_mobile
└── idx_status_created
members
├── uk_user
└── idx_level
member_relations
├── uk_parent_child
├── idx_parent_level
└── idx_child
member_upgrade_requests
├── uk_request_no
├── idx_user_status
└── idx_reviewer_status
products
├── idx_category_status
├── idx_status_sort
└── idx_created
product_skus
├── uk_sku_code
└── idx_product_status
cart_items
└── uk_cart_sku
addresses
└── idx_user_default
orders
├── uk_order_no
├── idx_user_status_created
└── idx_status_created
order_items
└── idx_order
payments
├── uk_payment_no
├── idx_order_status
└── uk_provider_trade_no
point_transactions
├── uk_transaction_no
├── idx_user_created
└── idx_reference
point_transfers
├── uk_transfer_no
├── idx_sender_created
└── idx_receiver_created
withdrawal_requests
├── uk_withdrawal_no
├── idx_user_status
└── idx_status_created
favorites
└── uk_user_product
follows
└── uk_user_target
browsing_histories
└── uk_user_product43. 外键策略
生产环境建议根据业务和数据量决定是否使用数据库 Foreign Key。
逻辑关系必须保证:
users.id
↓
members.user_id
↓
orders.user_id
↓
point_accounts.user_id但对于高并发、大规模商城:
可以采用:
数据库索引
+
应用层完整性检查
+
事务而不是依赖大量 FK。
无论是否使用 FK,应用层都必须验证数据归属。
44. 删除策略
核心业务数据不建议物理删除。
例如:
订单
支付
积分流水
提现
升级申请
审计日志不能直接:
DELETE推荐:
status
deleted_at或者永久保留。
45. 用户注销策略
用户注销后:
users.status = disabled而不是删除整个用户。
因为用户可能仍然存在:
订单
积分流水
提现
推荐关系
审计记录46. 会员升级事务
用户提交申请:
BEGIN
查询 members FOR UPDATE
↓
查询是否已有 pending
↓
读取当前等级
↓
读取下一等级
↓
检查业务条件
↓
INSERT member_upgrade_requests
↓
COMMIT审核通过:
BEGIN
查询 upgrade_request FOR UPDATE
↓
检查 status = pending
↓
检查审核人权限
↓
检查申请人关系
↓
查询 member FOR UPDATE
↓
再次验证当前等级
↓
修改 members.level_id
↓
更新 upgrade_request
↓
INSERT member_upgrade_logs
↓
INSERT audit_logs
↓
COMMIT47. 订单创建事务
BEGIN
锁定 SKU
↓
检查商品状态
↓
检查库存
↓
重新计算商品价格
↓
重新计算优惠
↓
重新计算积分
↓
重新计算运费
↓
创建订单
↓
创建 order_items
↓
锁定库存
↓
清理购物车
↓
写 order_logs
↓
COMMIT注意:
不能以浏览器提交的总金额作为订单金额依据。
48. 订单支付完成事务
支付回调:
BEGIN
验证第三方签名
↓
查询 payments FOR UPDATE
↓
幂等检查
↓
核对订单
↓
核对支付金额
↓
更新 payment
↓
更新 order
↓
记录 order_logs
↓
COMMIT49. 积分抵扣规则
现有系统页面显示:
100 积分 = 1 元建议数据库配置:
points_to_cent = 100例如:
100积分 → 100分人民币
500积分 → 500分人民币但最终允许抵扣多少,还需要配置:
订单商品
最大抵扣比例
商品是否允许积分抵扣
用户当前积分因此建议商品或系统配置增加:
points_discount_enabled
points_discount_rate50. 积分与订单的关系
订单应保存:
used_points
points_discount_cent例如:
商品金额:10000分
使用积分:500
积分抵扣:500分
实际支付:9500分同时生成:
point_transactions
type = order_use
reference_type = order
reference_id = order_id51. 提现业务模型
如果业务规则确实是:
积分 → 可提现那么建议不要简单把积分余额直接改成“钱”。
明确划分:
point_accounts
↓
积分
↓
提现申请
↓
withdrawal_requests
↓
财务处理这样可以避免:
购物抵扣积分
转账积分
可提现积分三个概念混为一谈。
如果实际上存在“现金余额”和“积分余额”两种资产,则应进一步拆成:
asset_accounts
asset_transactions不要继续共用一个 point_accounts。
52. 会员等级数据口径
目前前端检查发现:
会员平台:一星会员
商城个人中心:普通会员数据库设计上必须避免两套等级字段。
错误:
users.member_level = 1
mall_users.level = normal
members.level_id = 1推荐:
members.level_id作为唯一会员等级来源。
商城只读取:
members.level_id通过服务层统一转换为展示名称。
53. 推荐关系数据口径
同样不要出现:
users.referrer_id
team.parent_id
member.parent_id多个地方分别保存一份关系。
推荐关系唯一来源:
member_relations如有缓存字段:
users.direct_referrer_id只能作为冗余查询字段。
54. 商城商品数据口径
价格唯一来源:
product_skus.price_cent订单创建后:
order_items.price_cent作为历史成交价格快照。
即:
实时商品价格
↓
product_skus
历史订单价格
↓
order_items不能反过来读取当前商品价格显示历史订单。
55. 订单状态机
┌───────────────┐
│ pending_payment│
└───────┬───────┘
│ 支付
▼
┌───────────────┐
│pending_shipment│
└───────┬───────┘
│ 发货
▼
┌─────────┐
│ shipped │
└────┬────┘
│ 收货
▼
┌─────────┐
│completed│
└─────────┘
pending_payment
│
└──── 取消 → cancelled非法状态转换必须拒绝。
56. 会员升级状态机
pending
│
├── approve → approved
│
└── reject → rejected要求:
approved → 不允许再次审核
rejected → 不允许再次审核57. 提现状态机
pending
↓
reviewing
├── rejected
│
└── approved
↓
paid状态不能由客户端直接指定。
错误:
{
"status": "paid"
}正确:
提交申请 → pending
审核 → approved
财务打款 → paid58. 数据库事务隔离
涉及:
订单库存
积分
提现
会员升级建议至少考虑:
REPEATABLE READ并结合:
SELECT ... FOR UPDATE或乐观锁:
version具体选型由并发量和现有架构决定。
59. 并发控制
积分
使用:
行锁
或
version 乐观锁库存
使用:
available_stock更新:
UPDATE product_skus
SET stock = stock - ?
WHERE id = ?
AND stock >= ?通过受影响行数判断库存是否足够。
重复订单提交
使用:
Idempotency-Key60. 敏感字段存储原则
以下字段建议应用层加密:
身份证号
银行卡号以下字段数据库中可直接保存,但接口需要脱敏:
手机号
微信号
姓名数据库日志不能出现:
password
token
完整身份证
完整银行卡61. 数据备份
至少包含:
users
members
member_relations
member_upgrade_requests
products
product_skus
orders
order_items
payments
point_accounts
point_transactions
point_transfers
withdrawal_requests
audit_logs重点业务表需要:
每日备份
增量备份
异地备份
恢复演练62. 推荐数据库分库边界
V1 不建议一开始就物理分库。
推荐逻辑分域:
user
member
mall
order
asset
system数据库仍可以先:
一个 MySQL通过表前缀/代码模块区分:
users
members
products
orders
point_accounts后期数据量上升再考虑:
读写分离
分库
分表
缓存
消息队列63. 推荐缓存
可以缓存:
member_levels
categories
zones
product detail
service_configs
announcements不建议直接缓存作为最终数据源:
积分余额
订单状态
提现状态
会员等级
支付状态这些必须最终以数据库为准。
64. 推荐 Redis 数据
例如:
session:{user_id}
login:fail:{mobile}
rate_limit:login:{ip}
product:{id}
category:list
member:level:{id}积分余额如果做缓存,必须有严谨的一致性方案,不建议 V1 直接引入复杂缓存账本。
65. 数据字典
用户状态
0 disabled
1 active
2 locked会员状态
0 disabled
1 active升级状态
pending
approved
rejected
cancelled商品状态
draft
on_sale
off_sale订单状态
pending_payment
pending_shipment
shipped
completed
cancelled
refund支付状态
pending
paid
failed
cancelled
refunded提现状态
pending
reviewing
approved
rejected
paid
cancelled66. 推荐数据库命名规范
表名:
snake_case例如:
member_upgrade_requests主键:
id外键:
user_id
product_id
order_id时间:
created_at
updated_at状态:
status金额:
xxx_amount_cent数量:
quantity积分:
points67. 不建议的数据设计
不建议 1:订单直接保存商品名称 ID
错误:
orders.product_id因为一个订单可能包含多个商品。
应该:
orders
↓
order_items不建议 2:积分只保存一个余额
错误:
users.points推荐:
point_accounts
point_transactions不建议 3:提现直接修改积分
必须产生:
withdrawal_request
+
point_transaction并且考虑冻结。
不建议 4:会员等级存在多个表
只允许:
members.level_id作为权威数据。
不建议 5:前端传价格直接入库
错误:
{
"price": 99,
"total": 198
}服务端必须自己计算。
68. 推荐完整 ER 图
users
│
├── 1:1 ── user_profiles
├── 1:1 ── user_identities
├── 1:N ── user_bank_accounts
├── 1:1 ── members
│ │
│ └── N:1 ── member_levels
│
├── 1:N ── member_relations
│ ├── parent_user_id
│ └── child_user_id
│
├── 1:N ── member_upgrade_requests
│ │
│ ├── from_level_id
│ ├── to_level_id
│ └── 1:N member_upgrade_logs
│
├── 1:1 ── carts
│ └── 1:N cart_items
│
├── 1:N ── addresses
│
├── 1:N ── orders
│ ├── 1:N order_items
│ ├── 1:N payments
│ └── 1:N order_logs
│
├── 1:1 ── point_accounts
│ └── 1:N point_transactions
│
├── 1:N ── point_transfers
│
├── 1:N ── withdrawal_requests
│ └── 1:N withdrawal_logs
│
├── 1:N ── favorites ── N:1 products
├── 1:N ── follows
└── 1:N ── browsing_histories ── N:1 products
categories
└── 1:N products
├── 1:N product_skus
├── 1:N product_images
└── N:N zones
│
└── zone_products69. V1 核心表清单
第一阶段数据库至少建立:
users
user_profiles
members
member_levels
member_relations
member_upgrade_requests
member_upgrade_logs
categories
products
product_skus
carts
cart_items
addresses
orders
order_items
payments
order_logs
point_accounts
point_transactions
point_transfers
withdrawal_requests
withdrawal_logs
user_identities
user_bank_accounts
favorites
follows
browsing_histories
audit_logs
announcements70. 数据库开发优先级
P0:身份与会员
users
user_profiles
members
member_levels
member_relations
member_upgrade_requests
member_upgrade_logsP1:商城交易
categories
products
product_skus
carts
cart_items
addresses
orders
order_items
payments
order_logsP1:资产
point_accounts
point_transactions
point_transfers
withdrawal_requests
withdrawal_logsP2:账户扩展
user_identities
user_bank_accounts
favorites
follows
browsing_historiesP2:系统
announcements
audit_logs
service_configs71. 第一阶段数据库必须重点测试
用户
重复手机号
禁用用户
软删除用户
登录 Session推荐
自己推荐自己
重复推荐
循环推荐
不存在推荐人
禁用推荐人会员升级
跨级升级
重复申请
重复审核
越权审核
并发审核
审核后再次操作商品
库存不足
SKU 下架
商品下架
SKU 并发扣库存订单
重复创建
价格改变
库存改变
支付重复回调
订单越权
订单状态非法转换积分
余额不足
重复转账
并发转账
负数积分
自己转给自己提现
资料不完整
余额不足
重复提交
重复审核
并发提现
修改银行卡后的历史提现72. 最终数据库架构原则
系统最终必须保持以下几个“唯一数据源”:
用户身份
→ users
会员等级
→ members.level_id
会员等级定义
→ member_levels
推荐关系
→ member_relations
商品实时价格
→ product_skus.price_cent
订单历史价格
→ order_items.price_cent
订单状态
→ orders.status
支付状态
→ payments.status
积分余额
→ point_accounts
积分历史
→ point_transactions
提现状态
→ withdrawal_requests
系统操作记录
→ audit_logs避免同一事实在多个表中独立维护。
73. 数据一致性优先级
数据一致性优先于页面显示。
例如:
前端显示余额 = 1000
数据库余额 = 800最终必须以数据库账本为准。
同样:
前端显示订单已支付
数据库订单未支付应以支付回调验证后的服务端状态为准。
74. 推荐后续开发文档链路
数据库设计完成后,建议形成完整的技术文档链:
01 产品需求文档
↓
02 页面 / 原型文档
↓
03 API 接口文档
↓
04 数据库 ER + 字段设计
↓
05 权限设计
↓
06 状态机设计
↓
07 测试用例
↓
08 部署 / 运维文档最终前后端开发人员可以按照:
页面
↓
API
↓
Service
↓
数据库一条链路进行开发。
75. V1 数据库最终推荐架构
┌───────────────┐
│ users │
└───────┬───────┘
│
┌────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
会员域 商城域 资产域
│ │ │
┌─────┼─────┐ ┌────┼─────┐ ┌────┼─────┐
│ │ │ │ │ │ │ │ │
levels members relation products cart order points withdraw
│ │ │ │ │ │ │
│ │ SKU │ │ │ │
│ │ │ │ │ │
upgrade │ items │ transaction
request/logs │ │ transfer
│ │
team payment
│
logs
┌───────────────┐
│ system │
├───────────────┤
│ announcements │
│ audit_logs │
│ config │
└───────────────┘这套结构能够覆盖当前已检查出的会员推荐、等级升级、审核、团队、商城、订单、积分、转账、提现和用户资料功能,同时给后续后台管理、商家体系、多层团队和财务审核预留扩展空间。
现在三份文档已经形成一条完整开发链:
① 页面/原型 → ② API → ③ 数据库 ER/字段。
下一步最有价值的是把这三份继续整合成一份 《完整软件开发需求规格书 PRD》,然后再往下拆成 前端任务清单、后端任务清单、数据库建表 SQL、测试用例,开发团队就可以直接按 Sprint 开始执行。



