logo

数据库

D1 数据库使用和 Drizzle ORM

OPC Stack 使用 Cloudflare D1 和 Drizzle ORM。

数据库分成两类:

Meta DB
  全局身份
  全局配置
  支付订单
  兑换码
  shard registry

Tenant Shard DB
  用户积分账本
  用户反馈
  通知已读状态

绑定

META_DB 是全局元信息库。

TENANT_DB_0000..N 是租户分片库。

分片数量由环境变量控制:

D1_SHARD_COUNT=1

Schema

Meta schema:

src/db/schema.meta.ts
src/db/meta-migrations/

Tenant Shard schema:

src/db/schema.shard.ts
src/db/shard-migrations/

src/db/schema.ts 只作为统一导出口,不要把新表直接写进去。

Migration

pre-build.mjs 会自动生成并应用两套 migration。

Meta migration  -> META_DB
Shard migration -> 每个 TENANT_DB_xxxx

本地开发执行:

pnpm dev

部署执行:

pnpm deploycf

请求中使用数据库

API handler 中直接读取 request scoped DB。

const metaDb = ctx.get('metaDb')
const tenantDb = ctx.get('tenantDb')

全局数据使用 metaDb

用户级高频数据使用 tenantDb

不要写一个自动判断表归属的统一 db wrapper。

表归属规则

放 Meta DB:

登录前必须访问的数据
全局唯一约束数据
跨用户关系数据
支付订单和 webhook 状态
兑换码状态

放 Tenant Shard DB:

只属于单个用户的数据
高频用户写入数据
可通过 user_id 路由的数据

跨库写入

D1 不支持跨数据库事务。

跨库流程必须显式建模为最终一致。

兑换码流程:

Meta DB: unused -> claimed
Tenant DB: grant credits with source_type + source_id
Meta DB: claimed -> granted

租户库发放失败时接口返回 202 CREDIT_GRANT_PENDING,后台任务用同一个 source_type + source_id 重试。

常见问题

Q: 扩容会迁移老用户吗

不会。扩容只新增 shard,老用户继续使用 user_shards 中已有的 shard。

Q: 可以缩容吗

默认不支持。模板只提供扩容机制。