创建时间: 2026-09-01最后更新: 2026-09-01

1. 环境

本地开发把 PostgreSQL、FastAPI 和数据放在一台电脑上,生产环境则需要分别考虑应用实例、数据库服务、网络、权限、备份和监控。

生产连接信息只通过部署环境或密钥服务提供:

production.env.example
1
DATABASE_URL=postgresql+psycopg://task_app_runtime:REPLACE_WITH_SECRET@db.example.internal:5432/task_app?sslmode=verify-full&sslrootcert=/run/secrets/postgresql-ca.pem&connect_timeout=5

真实密码由部署平台的密钥服务注入,不能提交到代码仓库。日志也不能完整打印 URL,因为 URL 中通常包含用户名和密码。手动拼接 URL 时,密码中的 @、:、/ 等保留字符还需要进行百分号编码;条件允许时,优先使用结构化配置创建连接参数。

数据库地址应该位于受控私有网络,不要为了连接方便直接把 5432 端口向整个互联网开放。示例中的 sslmode=verify-full 会同时验证证书链和数据库主机名,sslrootcert 指向部署环境中受信任的根证书;如果数据库使用公共 CA,也可以按平台说明使用系统信任库。只写 verify-full 却没有提供可用的信任根,连接仍然无法建立。

connect_timeout=5 限制建立新数据库连接时的等待时间,它与后文的 pool_timeout 不是同一件事:前者等待网络连接建立,后者等待应用从连接池中取得一个连接。

开发、测试、预发布和生产使用不同数据库与账号。环境隔离不仅防止测试脚本清空生产数据,也让权限、迁移和容量问题能在发布前被发现。

应用启动时不自动执行 create_all(),也不让每个 worker 同时运行 Alembic。数据库结构升级应该是发布流程中的独立步骤。

2. 权限

生产应用使用最小权限账号。运行接口通常只需要连接、使用 Schema、读取和修改业务表:

runtime-permissions.sql
01
REVOKE CONNECT ON DATABASE task_app FROM PUBLIC;
02
GRANT CONNECT ON DATABASE task_app
03
TO task_app_runtime, task_app_migrator;
04
05
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
06
GRANT USAGE ON SCHEMA public TO task_app_runtime;
07
GRANT USAGE, CREATE ON SCHEMA public TO task_app_migrator;
08
09
GRANT SELECT, INSERT, UPDATE, DELETE
10
ON ALL TABLES IN SCHEMA public
11
TO task_app_runtime;
12
GRANT USAGE, SELECT
13
ON ALL SEQUENCES IN SCHEMA public
14
TO task_app_runtime;

PUBLIC 表示所有数据库角色。先撤销数据库的公共连接权限和 public Schema 的公共创建权限,再对所需角色逐项授权,才能让后续的 GRANT 真正形成边界。实际项目还要为管理员、监控和备份账号单独授权。

创建和修改表的迁移账号应与运行账号分开。接口被攻击时,运行账号不应该拥有创建表、DROP TABLE、创建角色或修改数据库配置的能力。

为了让未来迁移创建的表自动获得运行权限,需要由对象所有者设置默认权限:

default-permissions.sql
1
ALTER DEFAULT PRIVILEGES FOR ROLE task_app_migrator
2
IN SCHEMA public
3
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO task_app_runtime;
4
5
ALTER DEFAULT PRIVILEGES FOR ROLE task_app_migrator
6
IN SCHEMA public
7
GRANT USAGE, SELECT ON SEQUENCES TO task_app_runtime;

ALTER DEFAULT PRIVILEGES 只影响以后由 task_app_migrator 创建的对象,不会自动补授权已有表,而且必须由该角色本身、该角色的成员或管理员执行。若迁移实际使用了另一个对象创建者,这组默认权限不会生效。权限脚本需要在目标环境验证,不能只在拥有超级用户权限的本地数据库中测试。

正在验证登录状态
请稍候,验证完成后将继续显示文章内容