Python 关系数据库
此生成器创建一个新的 Python 关系数据库项目,由 Amazon Aurora(PostgreSQL 或 MySQL)提供支持,使用 SQLModel 进行数据建模,使用 Alembic 进行架构迁移。它生成应用程序代码和基础设施,使用 AWS CDK 或 Terraform 来配置和管理数据库,具有声明式架构定义、自动迁移部署和数据库客户端。
生成关系数据库
Section titled “生成关系数据库”- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - py#rdb - 填写必需参数
- 点击
Generate
pnpm nx g @aws/nx-plugin:py#rdbyarn nx g @aws/nx-plugin:py#rdbnpx nx g @aws/nx-plugin:py#rdbbunx nx g @aws/nx-plugin:py#rdb| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| name 必需 | string | - | 要生成的数据库项目名称 |
| directory | string | packages | 存储应用程序的目录。 |
| subDirectory | string | - | 项目所在的子目录。默认为项目名称。 |
| infra | aurora | none | aurora | 要配置的关系数据库服务。 |
| engine | postgres | mysql | postgres | 与所选服务一起使用的数据库引擎。 |
| databaseUser | string | dbadmin | 数据库管理员用户名。默认为 'dbadmin'。 |
| databaseName | string | - | 初始数据库名称。默认为项目名称。 |
| framework | sqlmodel | sqlmodel | 用于生成项目的 ORM 框架。 |
| iac | inherit | cdk | terraform | inherit | 首选的 IaC 提供商。默认情况下,这继承自您的初始选择。 |
| preferInstallDependencies | boolean | true | 是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);最后统一安装一次。 |
生成器在 <directory>/<name> 目录中创建以下项目结构:
文件夹<name>
- __init__.py 包导出(
get_engine、session_context) - connection.py 带 IAM 身份验证的数据库引擎和会话工厂
- utils.py 运行时配置和本地开发助手
- migration_handler.py 在部署期间运行 Alembic 迁移的 Lambda 处理程序
- create_db_user_handler.py 在部署期间创建应用程序数据库用户的 Lambda 处理程序
文件夹models
- example.py 示例 SQLModel 表定义
- __init__.py 包导出(
文件夹migrations
- versions Alembic 生成的迁移脚本
- env.py Alembic 环境(连接到数据库)
- script.py.mako Alembic 迁移脚本模板
- alembic.ini Alembic 配置
- config.json 本地开发连接详细信息和运行时配置键
- Dockerfile.migration 迁移处理程序的容器镜像
- Dockerfile.create-db-user create-db-user 处理程序的容器镜像
- project.json 项目配置和构建目标
本地开发脚本在所有数据库项目之间共享,并生成到 packages/common/scripts/ 中:
文件夹packages/common/scripts/src/rdb
- pull-image.ts 拉取数据库容器镜像
- start-container.ts 启动本地数据库容器
- wait-for-postgres-db.ts 等待本地数据库就绪(PostgreSQL)
- wait-for-mysql-db.ts 等待本地数据库就绪(MySQL)
由于该生成器会根据您选择的 iacProvider 以基础设施即代码的形式输出,它将在 packages/common 目录下创建一个包含相关 CDK 构造体或 Terraform 模块的项目。
通用的基础设施即代码项目结构如下:
文件夹packages/common/constructs
文件夹src
文件夹app/ 针对特定项目/生成器的基础设施构造体
- …
文件夹core/ 被
app目录构造体重用的通用构造体- …
- index.ts 导出
app目录构造体的入口文件
- project.json 项目构建目标与配置
文件夹packages/common/terraform
文件夹src
文件夹app/ 针对特定项目/生成器的 Terraform 模块
- …
文件夹core/ 被
app目录模块重用的通用模块- …
- project.json 项目构建目标与配置
文件夹packages/common/constructs/src
文件夹app
文件夹dbs
- <name>.ts 特定于您的数据库的基础设施
文件夹core
文件夹rdb
- aurora.ts 通用 Aurora 数据库构造
文件夹packages/common/terraform/src
文件夹app
文件夹dbs
文件夹<name>
- <name>.tf 特定于您的数据库的模块
文件夹core
文件夹rdb
文件夹aurora
- aurora.tf 通用 Aurora 模块
已部署的数据库具有以下架构。默认情况下,Amazon RDS Proxy 位于 Aurora 集群前面,用于池化连接并启用 IAM 身份验证 — 有关替代方案,请参阅禁用 RDS Proxy。无论您选择 PostgreSQL 还是 MySQL 引擎,架构都是相同的;只有 Aurora 引擎类型不同。
生成的项目使用 SQLModel 来定义数据库架构。工作流程是模型优先的:在数据库项目的 <name>/models/ 目录下添加或更新 SQLModel 表类,然后从这些模型更改生成迁移。
示例模型:
from sqlalchemy import Column, Stringfrom sqlmodel import Field, SQLModel
class ExampleModel(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) name: str = Field(sa_column=Column(String(255), nullable=False)) description: str | None = Field(default=None, sa_column=Column(String(255), nullable=True))在 <name>/models/__init__.py 中导入您的模型,以便 Alembic 在自动生成期间可以发现它们。
添加或更新模型后,使用 Alembic 生成并应用迁移脚本。生成的 alembic 目标在运行之前会自动启动本地数据库容器:
pnpm nx run <project>:alembic revision --autogenerate -m "describe your change"yarn nx run <project>:alembic revision --autogenerate -m "describe your change"npx nx run <project>:alembic revision --autogenerate -m "describe your change"bunx nx run <project>:alembic revision --autogenerate -m "describe your change"这会在 migrations/versions/ 下生成一个新的迁移脚本。在应用之前请检查生成的脚本。
将迁移应用到本地数据库:
pnpm nx run <project>:migrateyarn nx run <project>:migratenpx nx run <project>:migratebunx nx run <project>:migrate当您部署 AWS 堆栈时,生成的基础设施会自动将生成的迁移应用到已部署的数据库。
应用现有迁移
Section titled “应用现有迁移”当您拉取其他开发人员创建的迁移文件时,将它们应用到本地数据库:
pnpm nx run <project>:migrateyarn nx run <project>:migratenpx nx run <project>:migratebunx nx run <project>:migrate运行 Alembic 命令
Section titled “运行 Alembic 命令”生成的 alembic 目标公开了 Alembic CLI,因此您可以对本地数据库运行任何 Alembic 命令。有关可用命令,请参阅 Alembic 命令参考。
pnpm nx run <project>:alembic <alembic-command>yarn nx run <project>:alembic <alembic-command>npx nx run <project>:alembic <alembic-command>bunx nx run <project>:alembic <alembic-command>停止本地数据库
Section titled “停止本地数据库”停止 dev(例如使用 Ctrl+C)会自动删除本地数据库容器,但保留命名卷,以便您的数据在重启后保持不变。
连接到数据库
Section titled “连接到数据库”从数据库包中导入 session_context 并将其用作异步上下文管理器以获取 AsyncSession:
from sqlmodel import select
from my_scope.my_db import session_contextfrom my_scope.my_db.models.example import ExampleModel
async def example(): async with session_context() as session: results = (await session.execute(select(ExampleModel))).all()数据库客户端会自动:
- 使用
RUNTIME_CONFIG_APP_ID环境变量从 AWS AppConfig 检索数据库配置 - 通过
boto3RDS Signer 为 IAM 身份验证生成临时身份验证令牌 - 使用
ssl.create_default_context()建立 TLS 连接
关系型数据库生成器会根据您选择的 iacProvider 创建 CDK 或 Terraform 基础设施。
CDK 构造在 common/constructs 中创建。示例用法:
import { MyDatabase } from ':my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); ... const db = new MyDatabase(this, 'Db', { vpc, vpcSubnets: { subnetType: SubnetType.PRIVATE_ISOLATED, } }); }}这将配置一个 Aurora 集群,包含 RDS Proxy、管理员凭证、应用程序数据库用户、运行时配置注册和迁移处理程序。
生成的基础设施会创建两个数据库用户:
- 管理员用户 - 在集群配置期间创建,凭证存储在 AWS Secrets Manager 中
- 应用程序用户 - 通过 Lambda 自定义资源创建,启用 IAM 身份验证,并对应用程序数据库具有 DML 权限(SELECT、INSERT、UPDATE、DELETE)
Terraform 模块在 common/terraform 中创建。示例用法:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database"
vpc_id = module.vpc.vpc_id database_subnet_ids = module.vpc.private_isolated_subnet_ids lambda_subnet_ids = module.vpc.private_subnet_ids
tags = local.common_tags}这将配置一个 Aurora 集群,包含 RDS Proxy、管理员凭证、create-db-user Lambda、运行时配置注册、迁移 Lambda 和容器注册表资源。
生成的基础设施会创建两个数据库用户:
- 管理员用户 - 在集群配置期间创建,凭证存储在 AWS Secrets Manager 中
- 应用程序用户 - 通过 Lambda 函数创建,启用 IAM 身份验证,并对应用程序数据库具有 DML 权限(SELECT、INSERT、UPDATE、DELETE)
应用程序用户会自动创建,使用随机名称和 IAM 身份验证。生成的数据库客户端已配置为使用短期 RDS 令牌以该用户身份进行身份验证,因此您的应用程序代码永远不会处理数据库密码。
您的 VPC 应包括公有子网、具有出口的私有子网和私有隔离子网。数据库可以在私有隔离子网中运行,而应用程序 Lambda 函数应在具有出口的私有子网中运行,以便它们可以访问 AWS 服务(如 AppConfig)。
const vpc = new Vpc(this, 'Vpc', { subnetConfiguration: [ { name: 'public', subnetType: SubnetType.PUBLIC, }, { name: 'private_with_egress', subnetType: SubnetType.PRIVATE_WITH_EGRESS, }, { name: 'private_isolated', subnetType: SubnetType.PRIVATE_ISOLATED, }, ],});module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 6.0"
name = "app" ... public_subnet_names = ["public"] private_subnet_names = ["private_with_egress"] intra_subnet_names = ["private_isolated"]
enable_nat_gateway = true single_nat_gateway = true}使用 connection 生成器将项目连接到此数据库 — 请参阅相关计算类型(例如 FastAPI、MCP 服务器、代理)的连接指南,了解访问数据库所需的基础设施配置。
RDS Proxy 配置
Section titled “RDS Proxy 配置”生成的基础设施默认包含一个 RDS Proxy,它位于您的应用程序和 Aurora 集群之间。RDS Proxy 提供以下几个优势:
- 连接池 - 维护一个可在应用程序实例之间共享的数据库连接池,减少建立新连接的开销
- 连接弹性 - 在 Aurora 实例替换或维护期间自动处理故障转移和重新连接
- IAM 身份验证 - 支持基于 IAM 的数据库身份验证,无需在应用程序代码中管理数据库凭证
- 增强的安全性 - 对所有连接强制执行 TLS 加密
禁用 RDS Proxy
Section titled “禁用 RDS Proxy”您可以按如下方式禁用 RDS 代理:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableRdsProxy: false,});当 RDS Proxy 被禁用时,您的应用程序将直接连接到 Aurora 集群端点。
默认情况下,RDS Proxy 是启用的。如果需要,您可以禁用它:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_rds_proxy = false}当 RDS Proxy 被禁用时,您的应用程序将直接连接到 Aurora 集群端点。
不使用 RDS Proxy 连接时的 SSL 要求
Section titled “不使用 RDS Proxy 连接时的 SSL 要求”Amazon RDS CA 捆绑包必须位于运行时的系统信任存储中。
ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pemRUN update-ca-trustADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /usr/local/share/ca-certificates/rds-global-bundle.crtRUN update-ca-certificatesZip Lambda 函数
Section titled “Zip Lambda 函数”对于 zip 部署的 Lambda 函数(例如 py#api FastAPI),Amazon Linux 2023 Lambda 执行环境的内置 CA 信任存储包含 RDS 使用的 Amazon Root CA。
使用 RDS Proxy 时,您无需在连接到数据库的运行时中配置 RDS CA 捆绑包。
为您的 Aurora 集群配置写入器和读取器实例。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... writer: ClusterInstance.serverlessV2('writer'), readers: [ClusterInstance.serverlessV2('reader')],});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... instance_count = 2 # 1 writer + 1 reader}无服务器容量
Section titled “无服务器容量”控制 Aurora Serverless v2 扩展限制以匹配您的工作负载。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... serverlessV2MinCapacity: 0.5, serverlessV2MaxCapacity: 8,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... serverless_min_capacity = 0.5 serverless_max_capacity = 8}固定特定的 Aurora 引擎版本。
默认情况下,生成的本地数据库容器镜像与默认的 Aurora 引擎版本匹配。如果您更改 Aurora 引擎版本,建议同时使用匹配的本地容器镜像版本以获得最大兼容性。请参阅 AWS 发布说明中的 Aurora PostgreSQL 版本 和 Aurora MySQL 版本 以确定相应的社区数据库版本。
本地数据库镜像在数据库项目根目录下生成的 config.json 文件的 localDev.image 字段中配置。当您更改引擎版本时,请更新该值。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraPostgresEngineVersion.VER_17_7,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "17.7"}import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "8.0.mysql_aurora.3.12.0"}默认情况下启用删除保护(CDK 中为 deletionProtection: true,Terraform 中为 deletion_protection = true),以保护 Aurora 集群免遭意外删除。
禁用删除保护
Section titled “禁用删除保护”您可以为预期会删除数据库的环境禁用删除保护,例如短期开发或预览堆栈。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false}CDK 构造默认保留 Aurora 集群(removalPolicy: RemovalPolicy.RETAIN)。当您希望 CDK 堆栈删除时对集群进行快照或销毁时,请更改此设置。
使用 RemovalPolicy.DESTROY 时,还必须在删除集群之前禁用删除保护。
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... removalPolicy: RemovalPolicy.SNAPSHOT,});对于应随堆栈一起删除数据库的临时环境:
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});Terraform 不使用 CDK 删除策略。默认情况下,模块在删除时创建最终快照(skip_final_snapshot = false)。要跳过临时环境的最终快照:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}日志记录和监控
Section titled “日志记录和监控”默认情况下,Performance Insights 在 Aurora 写入实例上启用(使用集群的 KMS 密钥加密)。您还可以将 Aurora 引擎日志导出到 CloudWatch Logs(Aurora PostgreSQL 使用 postgresql;Aurora MySQL 使用 audit、error、general 和 slowquery)。为每个数据库启用日志导出:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableCloudwatchLogs: true, enablePerformanceInsights: false, // disable if not required});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_cloudwatch_logs = true enable_performance_insights = false # disable if not required}加密密钥轮换
Section titled “加密密钥轮换”用于加密 Aurora 集群及其凭证密钥的 KMS 密钥默认启用自动密钥轮换。如果您的安全策略在外部管理轮换,请禁用它。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableKeyRotation: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_key_rotation = false}使用 connection 生成器将此项目与工作区中的其他项目集成。以下连接涉及此项目: