先定域,再定表
一套交易平台的表一旦跑起来,改动成本会随时间指数上升。所以在写第一张表之前,我们先把"域"定死:一张表只能属于一个域,域间只能通过业务号引用,不做跨域外键。
十个域与职责如下:
| 域 | 前缀 | 职责 |
|---|---|---|
| 统一账号域 | users | 消费者/供应商/门店/员工一个手机号一个账号,含档案、钱包、积分、收藏、足迹、消息 |
| 系统域 | sys | 账号-角色-菜单-权限-模块-部门(RBACM)、字典、配置、日志、通知、行政区划、短信、文件、定时任务、数据修复 |
| 内容域 | cms | 首页/栏目/文章/单页、模板与静态生成、Banner 与装修、协议与帮助、标签/评论/专题 |
| 客户关系域 | crm | 线索→客户→商机→合同→回款,含公海、会员等级、跟进、工单 |
| 供应链域 | bbc | 供应商、商品/SKU/阶梯价/加价规则/运费模板、订单与退款、仓储履约(入库/质检/库存/盘点/打包/发货)、采购与退货 |
| 同城域 | oo | 门店、门店商品、同城订单、即时配送与轨迹、评价、收藏 |
| 营销域 | active | 优惠券、满减、拼团、秒杀、套餐、砍价、预售、买赠、签到、积分 |
| 财务域 | fin | 科目凭证、资金账户、流水、充值提现、平台结算、佣金、退款冲正、费用、发票、对账、期末结账 |
| 分析域 | ana | 埋点与十个域的日聚合、业绩目标(只读) |
| 支付域 | pay | 渠道配置、统一收单、回调通知 |
分域的直接收益是权限与数据范围可以按前缀收口:给某个角色开"供应链-只读",就是给它 bbc_ 前缀的读权限,新增表天然继承,不会漏。
四条边界决策
边界模糊是这类系统最常见的技术债来源。我们在开工时就把四条争议点定下来:
- 仓储不是独立模块。入库、质检、盘点、打包、调拨、发货都属于供应链的子域,统一挂
bbc_。单独拆 WMS 只会让订单与库存的关联变成跨服务调用。 - 前台账号与后台账号是两套。
users承载 C 端消费者、供应商、花店老板、供应商员工、门店店员;sys_users是平台自己的后台操作员。两者不混用、不共表,避免"业务方登录后台"这种权限事故。 - 应付与应收分表。供应商应付结算走供应链域的结算单(我们欠供应商),下游买方的赊销应收走信用账期(买方欠我们)。方向相反,绝不能复用同一张表。
- 业务结算与资金台账不耦合。业务侧的应付结算单与平台级的资金账户、流水、提现、佣金、发票分开,二者靠业务号对账,不互相回写。这样平台自己的现金流报表不会被商户业务污染。
业务号:所有跨域引用的统一货币
每张业务表都有一个 biz_no,规则是"2~4 位大写前缀 + 时间 + 随机",长度控制在 32 位以内,例如:
| 前缀 | 含义 | 前缀 | 含义 |
|---|---|---|---|
BO / BOI | 订单 / 订单明细 | BSP / BP | 供应商 / 商品 |
BB / BBD | 应付结算单 / 明细 | CRA / CRH | 信用账户 / 额度占用 |
CRB / CRI | 账期账单 / 明细 | CRP / CRL | 回款 / 额度变更日志 |
OO / OOI | 同城订单 / 明细 | FA / FT | 资金账户 / 资金流水 |
好处是:看到单号就知道是哪类单据,客服与运维排查不用查字典;同时所有关联都走业务号,数据库迁移、分库分表、跨租户复制时不会因自增 ID 变化而断链。
两处"故意不统一"
有两件事我们刻意保持不一致,因为统一反而会破坏语义:
- 时间类型。账号、供应链、同城、营销、内容域用
INT UNSIGNED(秒级时间戳),系统、客户关系、财务、支付、分析域用DATETIME。前者便于按区间索引与前端直接消费,后者便于财务按自然日对账与人工核对。 - 状态枚举。订单状态、支付状态、结算状态各管一段,不做一张"万能状态表"。状态机的归属必须跟着业务走,否则一次改动会牵连所有域。
留好的扩展位
建库时就为后来的能力预留了位置,这一点在后续演进中被证明是省钱的:
- 所有业务表预留
is_deleted软删除与create_time/update_time; - 金额列统一
DECIMAL(12,2),数量列统一DECIMAL(12,3)(花材按扎、按枝都能表达); - 每张表预留租户两列的位置,为后续 SaaS 多租户形态做准备——这一条在两周后落地多租户时,把改造成本从"重设计"降到了"批量加列"。
数据库是这类平台最不容易返工的部分。先把域、业务号、时间与金额口径定死,后面加功能就只是加表,而不是改地基。