数据库

默认模板使用的两个 D1 数据库,以及各数据表的用途和关联关系。

默认模板使用两个独立的 Cloudflare D1 数据库。DB 保存业务数据,ANALYTICS_DB 保存第一方访问统计数据。两个数据库之间没有表关联,也不会在同一条 SQL 中跨库联表查询。

DB

项目内容说明
Binding 名称DBWorker 通过这个 Binding 访问业务数据库。
模板默认数据库名称saavo-template-db首次部署时,部署脚本会根据 Worker 名称重新生成。
初始化脚本schema/db-init.sql只用于初始化空数据库或手动重置数据库。
初始化标记表saas_userdb:migrate 通过这张表判断业务库是否已经初始化。

数据表

范围数据表用途
账号和认证saas_user、saas_session、two_factor_setup_session、email_verification_session、password_reset_session用户账号、登录会话、双重验证、邮箱验证和密码重置
OAuth 2.0oauth_auth_session、oauth_client、oauth_auth_code、oauth_token授权请求、客户端、授权码和 Token
角色和权益user_role_capability、user_entitlement_capability、capability_quota_event角色能力、权益能力和额度变化记录
Reactionevent_execution、command_executionEvent 和 Command 执行记录
支付webhook_events、payment_customers、checkout_sessions、purchase_items、subscriptions、subscription_items、transactions、transaction_items、refundsWebhook、Customer、Checkout、购买、订阅、交易和退款
联盟推广affiliate_payout_profiles、affiliate_commissions、affiliate_monthly_payouts、affiliate_monthly_payout_records收款资料、佣金、月度结算和付款记录
工单和内容ticket、newsletter_subscriber工单索引和邮件订阅
站内通知notification、user_notification通知内容及用户已读状态

实体关系

下面按业务模块分别列出主库的 ER 图。图中的关联关系来自字段含义以及 Repository 和 Service 中的实际查询,不以 SQL 是否声明 FOREIGN KEY 为准。为避免关系线过于密集,saas_user 等公共实体会重复出现在不同图中。

账号、认证和 OAuth 2.0

DB 账号、认证和 OAuth 2.0 逻辑 ER 图

saas_user.invited_by_id 形成用户之间的推荐关系。登录、验证和 OAuth 2.0 相关记录分别通过 user_id、client_id、oauth_code 等字段关联用户、客户端和授权码。

角色、权益和 Reaction

DB 角色、权益和 Reaction 逻辑 ER 图

角色能力、权益能力和额度变化记录都可以关联用户。能力授予记录中的 event_id 和 command_id 指向对应的 Reaction 执行记录;额度变化记录通过 Subject、来源、权益和能力等字段关联相应的权益能力记录。

支付

DB 支付逻辑 ER 图

payment_customers 记录用户账号与支付服务商 Customer 的对应关系。Checkout、订阅和交易可以通过本地 ID 关联,也可以结合 provider、connection_id 和支付服务商提供的 ID 确认同一笔业务数据。webhook_events 保存收到的 Webhook,并由此触发支付数据同步;一条 Webhook 记录不一定只对应某张支付表中的一条记录。

联盟推广

DB 联盟推广逻辑 ER 图

佣金记录同时关联推广者、被推荐用户、交易和交易明细。订阅佣金通过支付服务商、支付连接和订阅 ID 查找对应的订阅;月度结算按推广者、结算月份和币种汇总佣金,无需单独保存外键字段。

工单、通知和邮件订阅

DB 工单、通知和邮件订阅逻辑 ER 图

user_notification 是用户与通知之间的关联表。工单可关联提交人和处理人,其中 requester_id 小于或等于 0 时表示匿名提交,不对应 saas_user。邮件订阅只以邮箱地址保存,不与用户账号建立实体关系。

ANALYTICS_DB

项目内容说明
Binding 名称ANALYTICS_DBWorker 通过这个 Binding 访问访问统计数据库。
模板默认数据库名称saavo-template-analytics-db首次部署时,部署脚本会根据 Worker 名称重新生成。
初始化脚本schema/analytics-init.sql只用于初始化空数据库或手动重置数据库。
初始化标记表analytics_sessiondb:migrate 通过这张表判断统计库是否已经初始化。

数据表

数据表用途
analytics_session访问会话的访客标识、设备信息、第一次活动时间和第一次接收时间
analytics_event页面浏览和自定义事件,以及来源、设备、地区和性能指标
analytics_event_propertyEvent 的自定义属性
analytics_session_trait会话级自定义特征

实体关系

ANALYTICS_DB 逻辑 ER 图

analytics_event 和 analytics_session_trait 都通过 (site_id, session_id) 关联 analytics_session,analytics_event_property.event_id 关联 analytics_event.event_id。统计库中的这三组关系同时由 SQL 外键约束;其中 Event 属性和 Session Trait 会随所属记录一并删除。

字段约定

约定说明
时间除 SQL 明确说明外,*_at、*_start、*_end 一类字段使用 Unix 毫秒
布尔值D1 使用 INTEGER 保存布尔状态,通常以 1 表示是、0 表示否
金额*_minor 使用货币最小单位,例如人民币的分、美元的美分
JSONJSON 是 SQLite 的类型声明,实际内容仍以文本形式保存,并由应用或 CHECK 约束保证 JSON 有效
软删除deleted_at 通常以 0 表示未删除,非零值表示删除时间
主键WITHOUT ROWID 表使用声明的主键保存记录,不再额外提供隐式 rowid

初始化数据库和更新表结构

schema/db-init.sql 和 schema/analytics-init.sql 都包含 DROP TABLE IF EXISTS,只能用于初始化空数据库或手动重置数据库,不能用于更新生产环境的表结构。

数据库迁移文件统一放在 schema/migrations。业务库文件名采用 NNNN-db-description.sql,统计库文件名采用 NNNN-analytics-description.sql。需要修改生产环境的表结构时,应新增迁移文件,再执行 npm run db:migrate:remote。

不要在生产数据库中执行初始化脚本

初始化脚本会删除已有表和数据。db:reset:local 与 db:reset:remote 也会清空数据库,只能在确定需要重建数据库时使用。