Convex 自托管后端接入 Postgres 与 MySQL:环境变量、连接配置与源码原理
2026/9/23 15:03:47 网站建设 项目流程
  • 数据库
  • 后端

【免费下载链接】convex-backend

The open-source reactive database for app developers

项目地址:https://gitcode.com/gh_mirrors/co/convex-backend
点击查看免费下载

导读

Convex 是一个开源响应式数据库后端,默认以 SQLite 作为本地持久化存储;但对于需要高可用与托管运维的生产环境,官方推荐将后端连接到托管式 Postgres 或 MySQL 服务。本文基于仓库 self-hosted/advanced/postgres_or_mysql.md 展开,完整讲解POSTGRES_URLMYSQL_URLINSTANCE_NAMEDO_NOT_REQUIRE_SSL等环境变量的用法与数据库命名规则,并结合仓库源码(如 crates/db_connection/src/lib.rs、crates/clusters/src/lib.rs、self-hosted/docker-build/run_backend.sh)剖析后端如何解析连接串、派生数据库名、注入 SSL 参数,让读者既能照着文档完成 Neon/PlanetScale/本地 Postgres/MySQL 的接入,也能理解底层实现原理。

一、为什么生产环境要考虑 Postgres 或 MySQL

Convex 后端本身被设计为同时兼容 SQLite、Postgres 与 MySQL 三种数据库。默认情况下,self-hosted/docker/docker-compose.yml 中的 Docker 镜像使用本地 SQLite 存储(数据存放在 Docker volumedata:/convex/data中)。

  • SQLite 方案适合本地开发与快速起步,是官方推荐的入门配置(详见 self-hosted/README.md);
  • 如果运行的是需要保证可用性(guaranteed uptime)的生产负载,则应优先选择托管式 Postgres 或 MySQL 服务,例如 Neon(Postgres)或 PlanetScale(MySQL/Vitess);
  • 官方测试确认 Convex 后端可与Postgres v17MySQL v8协同工作,其他版本也可能兼容,但未做验证。

需要特别注意一个硬性约束:后端必须与数据库托管在同一区域,且网络距离尽可能近。后端与数据库之间的任何额外延迟都会直接拖累查询性能,这一点在 postgres_or_mysql.md 中被反复强调。

1.1 迁移前先导出数据

在不同数据库提供方之间迁移时,务必先使用官方 CLI 导出数据:

npx convex export

该命令会将当前部署的数据导出为文件,随后再在新数据库环境上执行npx convex deploy重新部署 Convex 函数(详见下文“部署后的重部署”说明)。

二、环境变量速查表

以下变量在接入外部数据库时最常用,全部在 docker-compose.yml 的environment段中透传,并由容器入口脚本 self-hosted/docker-build/run_backend.sh 消费:

环境变量作用取值要点
POSTGRES_URL指定 Postgres 连接串,优先级最高不含数据库名与查询参数,形如postgresql://user@host:5432
MYSQL_URL指定 MySQL 连接串不含数据库名,形如mysql://user:pass@host:3306
DATABASE_URL已弃用,兼容旧行为,等价于 Postgres 连接设置时会打印弃用警告
DO_NOT_REQUIRE_SSL关闭对数据库连接的 SSL 强制要求仅建议本地开发使用;设置后若存在 SSL 仍会优先使用
INSTANCE_NAME指定实例名,间接决定数据库名默认convex-self-hosted,连字符会被替换为下划线
INSTANCE_SECRET实例密钥,与INSTANCE_NAME配对后端启动必需

从 run_backend.sh 的入口逻辑可以看出完整的优先级链:

if [ -n "$POSTGRES_URL" ]; then DB_SPEC="$POSTGRES_URL" DB_FLAGS=("${POSTGRES_DB_FLAGS[@]}") # --db postgres-v5 elif [ -n "$MYSQL_URL" ]; then DB_SPEC="$MYSQL_URL" DB_FLAGS=("${MYSQL_DB_FLAGS[@]}") # --db mysql-v5 elif [ -n "$DATABASE_URL" ]; then # 弃用警告,按 Postgres 处理以保持向后兼容 else DB_SPEC="$SQLITE_DB" # 回退到 SQLite fi

即:POSTGRES_URL>MYSQL_URL>DATABASE_URL(弃用)> SQLite 回退。最终这些参数被拼装为convex-local-backend的命令行参数--db postgres-v5 <DB_SPEC>--db mysql-v5 <DB_SPEC>postgres-v5/mysql-v5对应 crates/clusters/src/db_driver_tag.rs 中的DbDriverTag枚举值),同时--instance-name "$INSTANCE_NAME"${DO_NOT_REQUIRE_SSL:+--do-not-require-ssl}等参数也会一并传入。

三、连接 Neon 上的托管 Postgres(生产场景)

3.1 获取连接串并建库

从 Neon 控制台复制连接字符串,并创建后端专用的数据库:

export DATABASE_CONNECTION='<connection string>' psql $DATABASE_CONNECTION -c "CREATE DATABASE convex_self_hosted"

3.2 构造 POSTGRES_URL

POSTGRES_URL不含数据库名和查询参数的连接串。以 Neon 为例,其结尾应为neon.tech。文档给出了用sed剥掉路径与查询串的做法:

export POSTGRES_URL=$(echo $DATABASE_CONNECTION | sed -E 's/\/[^/]+(\?.*)?$//')

该正则将形如postgresql://user:pass@ep-xxx.neon.tech/convex_self_hosted?sslmode=require的完整连接串中的/convex_self_hosted?sslmode=require部分剥离,得到postgresql://user:pass@ep-xxx.neon.tech

3.3 在托管平台上注册环境变量

  • 若运行在 Fly.io 等平台,通过平台命令注册密钥:
fly secrets set POSTGRES_URL=$POSTGRES_URL
  • 若在本机运行,直接重启后端容器即可让环境变量生效(POSTGRES_URL已在 docker-compose.yml 的environment中声明透传)。

3.4 验证连接并重部署函数

启动后端后检查日志,应能看到类似Connected to Postgres的行。这一日志来自 crates/db_connection/src/lib.rs:

tracing::info!("Connected to Postgres database: {}", deployment_name);

另外,切换到新数据库后,必须重新部署已有的 Convex 函数

npx convex deploy

3.5 为什么 URL 中不能带数据库名:源码剖析

在 crates/clusters/src/lib.rs 中,Postgres 分支会校验连接串路径必须为空或/,否则直接报错:

anyhow::ensure!( cluster_url.path() == "" || cluster_url.path() == "/", "cluster url already contains db name: {}", cluster_url.path() );

随后后端依据deployment_name(即实例名)自动拼接数据库名:

let db_name = deployment_name.replace('-', "_"); cluster_url.set_path(&db_name);

这正是“不要在POSTGRES_URL中包含数据库名”的根本原因——数据库名由后端根据实例名自动计算并写入连接串路径。

四、本地连接 Postgres(开发场景)

本地已有 Postgres 实例时:

psql postgres -c "CREATE DATABASE convex_self_hosted"

然后设置连接串并关闭 SSL 强制要求

export POSTGRES_URL='postgresql://<your-username>@host.docker.internal:5432' export DO_NOT_REQUIRE_SSL=1 docker compose up

要点说明:

  • host.docker.internal用于从 Docker 容器内访问宿主机上的 Postgres;
  • 同样不要POSTGRES_URL中包含数据库名;
  • DO_NOT_REQUIRE_SSL对应后端--do-not-require-ssl参数。其语义在 crates/local_backend/src/config.rs 中有明确注释:关闭后不强制要求数据库连接使用 SSL,但如果数据库支持 SSL,仍会优先使用;官方注释强调该选项“只应在测试中设置”。

4.1 SSL 参数如何注入:源码验证

在 crates/clusters/src/lib.rs 中,adjust_postgres_url会根据require_sslrequire_leader标志向连接串追加查询参数:

if require_ssl { cluster_url .query_pairs_mut() .append_pair("sslmode", "require"); } if require_leader { cluster_url .query_pairs_mut() .append_pair("target_session_attrs", "read-write"); }

因此设置了DO_NOT_REQUIRE_SSL时不会注入sslmode=require;而在 Neon 等托管场景(默认强制 SSL),后端会注入sslmode=require,并对会话附加target_session_attrs=read-write(要求连接到可写的 leader 节点,见 crates/db_connection/src/lib.rs 的TargetSessionAttrs::ReadWrite)。

五、本地连接 MySQL(开发场景)

mysql -e "CREATE DATABASE convex_self_hosted;" export MYSQL_URL=mysql://<your-username>@host.docker.internal:3306 export DO_NOT_REQUIRE_SSL=1 docker compose up

与 Postgres 一致:数据库名由后端推导,URL 中不要带库名。

六、连接 PlanetScale 上的 MySQL(生产场景)

在 PlanetScale 创建数据库,必须命名为convex_self_hosted,然后:

export MYSQL_URL=mysql://<your-username>:<your-password>@aws.connect.psdb.cloud docker compose up

6.1 MySQL 分支的源码行为

从 crates/clusters/src/lib.rs 可以看出 MySQL 分支与 Postgres 的关键差异:后端不会把数据库名写入连接串路径,而是保持无库连接、在持久化层按需USE对应的库:

// NOTE: We do not set any database so we can reuse connections between // database. The persistence layer will select the correct database. if require_ssl { cluster_url .query_pairs_mut() .append_pair("require_ssl", "true") .append_pair("verify_ca", "true"); } let db_name = deployment_name.replace('-', "_");

即:db_name同样由实例名推导(-替换为_),但以独立字段PersistenceArgs::MySql { url, db_name, ... }传递,供 crates/db_connection/src/lib.rs 中ConvexMySqlPool连接后选择数据库。MySQL 路径还要求连接串用户名非空(crates/clusters/src/lib.rs),若缺失会报cluster url username must be set且不打印完整 URL 以防泄露密码。

七、数据库命名规则与 INSTANCE_NAME

后端使用的持久化数据库名 = 实例名(instance name)中-替换为_后的结果:

实例名实际连接的数据库
convex-self-hosted(默认)convex_self_hosted
your-instance-nameyour_instance_name

在 Docker 容器中通过INSTANCE_NAME环境变量设置实例名。例如使用 Postgres:

export POSTGRES_URL='<connection string>' export INSTANCE_NAME='your-instance-name' psql $POSTGRES_URL -c "CREATE DATABASE your_instance_name;"

源码侧,LocalConfig::name()(crates/local_backend/src/config.rs)在未设置INSTANCE_NAME时回退到DEV_INSTANCE_NAME

pub fn name(&self) -> String { self.instance_name .clone() .unwrap_or(DEV_INSTANCE_NAME.to_owned()) }

DEV_INSTANCE_NAME定义于 crates/keybroker/src/lib.rs,取自常量文件 crates/keybroker/dev/instance_name.txt(内容为carnitas),用于本地开发;Docker 镜像的入口脚本 run_backend.sh 则始终透传--instance-name "$INSTANCE_NAME",因此容器内默认实例名由镜像默认值决定(即文档所述convex-self-hosted)。随后deployment_name.replace('-', "_")即产生convex_self_hosted,这与前文所有建库命令中的库名完全对应。

八、连接流程全景:从环境变量到持久化层

综合 run_backend.sh、crates/db_connection/src/lib.rs 与 crates/clusters/src/lib.rs,一条完整调用链如下:

  1. 容器入口脚本读取POSTGRES_URL/MYSQL_URL(或回退 SQLite),组装--db postgres-v5/--db mysql-v5--do-not-require-ssl--instance-name等参数;
  2. convex-local-backend解析参数(LocalConfig),得到DbDriverTagdb_spec(连接串)、实例名;
  3. persistence_seed/connect_persistence(crates/db_connection/src/lib.rs)调用persistence_args_from_cluster_url(crates/clusters/src/lib.rs):
    • 校验用户名非空、路径不含库名;
    • Postgres:路径写入推导出的库名,按需注入sslmode=requiretarget_session_attrs=read-write
    • MySQL:保持无库连接,注入require_ssl=true&verify_ca=true,库名单独传递;
  4. 创建连接池(PostgresPersistence::create_pool/ConvexMySqlPool::new),初始化持久化层;
  5. 日志分别输出Connected to Postgres database: {deployment_name}Connected to MySQL database: {db_name}(crates/db_connection/src/lib.rs 与 crates/db_connection/src/lib.rs)。

九、常见问题与注意事项

  • 连接串必须可被 URL 解析:后端使用 Rusturl库解析连接串,Postgres 路径带库名会直接报错;用户名缺失会报cluster url username must be set
  • SSL 策略:托管服务(Neon、PlanetScale)默认强制 SSL;本地开发可用DO_NOT_REQUIRE_SSL=1关闭强制要求,但官方建议仅测试环境使用。
  • 数据库需预先创建:后端不会自动建库,所有示例都先用psql/mysql客户端显式CREATE DATABASE
  • 迁移数据与函数:切换数据库提供方前先npx convex export导出数据;切换后需npx convex deploy重新部署函数。
  • 延迟敏感:后端与数据库必须在同一区域就近部署,否则查询性能会显著下降。
  • DATABASE_URL已弃用:旧配置中若使用DATABASE_URL,启动日志会打印弃用警告,并仍按 Postgres 语义处理以保持向后兼容(见 run_backend.sh)。

十、扩展阅读

  • self-hosted/README.md:自托管总览,包含 Docker 启动、admin key 生成与前端对接;
  • self-hosted/docker/docker-compose.yml:完整环境变量清单;
  • self-hosted/advanced/hosting_on_own_infra.md:自有基础设施托管方案;
  • self-hosted/advanced/fly/README.md:Fly.io 托管方案(含 secrets 配置);
  • self-hosted/advanced/railway/README.md:Railway 托管方案;
  • self-hosted/advanced/upgrading.md:版本升级指南;
  • crates/db_connection/src/lib.rs 与 crates/clusters/src/lib.rs:持久化连接与连接串解析的实现源码。
  • 数据库
  • 后端

【免费下载链接】convex-backend

The open-source reactive database for app developers

项目地址:https://gitcode.com/gh_mirrors/co/convex-backend
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询