数据库与本地代理
开通平台数据库后,每个 App 都有相互隔离的 Preview 和 Production 数据库。应用运行时直接读取 DATABASE_URL,不需要在源码中保存数据库地址、账号或密码。
Preview、Production 数据库分别在达到 5 GiB 时产生容量提醒。该值是软告警线,不会自动停止写入;文件类内容应使用 App Storage,而不是写入 MySQL。其他默认限制见资源与文件限制。
本地开发完成的数据库结构不是通过上传整库或手工登录 Production 上线,而是作为版本化 migration 与应用代码一起发布:deploy 先验证 Preview,promote --yes 再把同一批 migration 应用到 Production,成功后才切换应用版本。
应用连接数据库
Node.js 和 Python 可以继续使用熟悉的数据库工具,例如 Prisma、Knex、Sequelize、SQLAlchemy 或 Alembic。SDK 不替代 ORM,也不要求使用某一种 ORM。
const databaseUrl = process.env.DATABASE_URL;
import os
database_url = os.environ["DATABASE_URL"]
应该把 SQL 整理成什么
每次表结构变化都创建一个新的、有顺序的 migration 文件,并与实现该功能的代码放在同一次 Git 提交中。已经执行过的 migration 不再改写;需要修正时继续增加下一份 migration。
以下内容适合进入 migration:
- 新建或修改表、字段、索引;
- 为新功能准备少量、可重复写入的必要初始配置;
- 分阶段兼容新旧代码的数据修复。
以下内容不会由平台自动从本地复制到 Production:
- 本机或 Preview 中的测试数据;
- 整库 SQL 导出、数据库备份;
- 只在图形化客户端里手工执行、没有保存到项目的 SQL;
- 大批量业务数据导入。
Node.js 目录示例
使用 Prisma、Knex、Sequelize 等工具时,保留工具生成的 migration 目录。例如 Prisma 项目:
my-app/
├── prisma/
│ ├── schema.prisma
│ └── migrations/
│ ├── 20260918090000_init/migration.sql
│ └── 20260918103000_add_status/migration.sql
├── src/
├── package.json
├── package-lock.json
└── xdb-paas-deploy.yaml
先把 migration 工具作为项目依赖安装并提交锁文件:
npm install prisma @prisma/client
package.json 提供一个无需交互、执行完会自动退出的命令:
{
"scripts": {
"db:migrate": "prisma migrate deploy"
}
}
prisma/schema.prisma 从平台环境变量读取连接,不填写固定账号密码:
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
然后在 xdb-paas-deploy.yaml 中声明:
database:
provider: mysql
migrate_command: npm run db:migrate
如果项目直接维护 .sql 文件,可以采用下面的结构:
my-app/
├── db/migrations/
│ ├── 001_create_customer_note.sql
│ └── 002_add_note_status.sql
├── scripts/migrate.mjs
├── package.json
└── xdb-paas-deploy.yaml
scripts/migrate.mjs 需要按文件名顺序执行尚未运行的文件,并把已完成版本写入项目自己的 migration 记录表;不要每次启动都无条件重放全部 SQL。对应命令可以配置为 node scripts/migrate.mjs。
Python 目录示例
使用 Alembic 的项目通常保留下面这些文件:
my-app/
├── alembic/
│ ├── env.py
│ └── versions/
│ ├── 20260918_01_init.py
│ └── 20260918_02_add_status.py
├── alembic.ini
├── app/
├── requirements.txt
└── xdb-paas-deploy.yaml
requirements.txt 或 pyproject.toml 中声明 Alembic 和项目使用的 MySQL 驱动,并配置:
alembic
SQLAlchemy
PyMySQL
alembic/env.py 读取平台连接串;使用 PyMySQL 时可把驱动名补到 URL 中:
import os
from alembic import context
config = context.config
database_url = os.environ["DATABASE_URL"]
config.set_main_option(
"sqlalchemy.url",
database_url.replace("mysql://", "mysql+pymysql://", 1),
)
再配置部署命令:
database:
provider: mysql
migrate_command: python -m alembic upgrade head
无论使用哪种语言,migration 工具、数据库驱动、migration 文件和锁文件都必须进入上传内容,命令不能依赖开发电脑全局安装的软件。
平台什么时候执行 migration
完整发布顺序如下:
xdbapp deploy构建不可变版本;- 平台向隔离 Job 注入 Preview
DATABASE_URL,执行migrate_command; - migration 和 Preview 健康检查都成功后,返回 Preview URL;
- 验收后执行
xdbapp promote <deployment-id> --yes; - 平台向隔离 Job 注入 Production
DATABASE_URL,再次执行同一migrate_command; - Production migration 成功后,才启动新 Production 容器并切换流量。
因此客户不需要、也拿不到 Production RDS 的公网账号和密码。
平台能保证 Production migration 报错时不切换应用流量,但 MySQL 已经成功执行的前半部分 SQL 不会自动撤销。修复后重试时,同一命令还会再次执行。
推荐使用 expand/contract:先新增表或字段,让新旧代码都能工作;完成切换并稳定运行后,再在后续版本清理旧结构。不要在同一次发布中直接删除旧版本仍依赖的字段。
xdbapp rollback 只回退应用代码和运行配置,不反向执行旧 migration,也不恢复业务数据。需要修复数据库时,应创建一份新的、向前执行的 migration。
本地验证 migration
xdbapp dev -- 可以把 Preview DATABASE_URL 安全注入一个本地子进程,所以可以在发布前先运行同一命令:
# Node.js
xdbapp dev -- npm run db:migrate
# Python
xdbapp dev -- python -m alembic upgrade head
这一步连接的是 Preview 数据库,不是本机数据库,也不是 Production。之后 xdbapp deploy 仍会自动再执行一次,因此 migration 必须能识别已经完成的版本。
迁移失败时查看构建日志:
xdbapp inspect <deployment-id>
xdbapp logs --deployment <deployment-id> --type build
本地连接 Preview 数据库
xdbapp db proxy
CLI 会在本机 127.0.0.1 打开一个临时端口,并通过加密通道连接平台内网中的 Preview 数据库。RDS 不需要开放公网。
命令会临时显示本地连接信息;按 Ctrl+C 后代理立即关闭。也可以指定本地端口:
xdbapp db proxy --port 13306
数据库代理只连接 Preview,不连接 Production,并且只接受通过商家后台登录获得的管理员或开发者凭据。普通部署令牌和 CI 令牌不能使用该能力。