TypeScript 关系数据库
此生成器创建一个由 Amazon Aurora(PostgreSQL 或 MySQL)和 Prisma ORM 支持的新关系数据库项目。它生成应用程序代码和基础设施,使用 AWS CDK 或 Terraform 来配置和管理数据库,具有声明式架构定义、自动迁移部署和类型安全的 ORM 客户端。
生成关系数据库
Section titled “生成关系数据库”您可以通过两种方式生成新的关系数据库项目:
pnpm nx g @aws/nx-plugin:ts#rdbyarn nx g @aws/nx-plugin:ts#rdbnpx nx g @aws/nx-plugin:ts#rdbbunx nx g @aws/nx-plugin:ts#rdb- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - ts#rdb - 填写必需参数
- 点击
Generate
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| name 必需 | string | - | 要生成的数据库项目名称 |
| directory | string | packages | 存储应用程序的目录。 |
| subDirectory | string | - | 项目所在的子目录。默认为项目名称。 |
| infra | aurora | none | aurora | 要配置的关系数据库服务。 |
| engine | postgres | mysql | postgres | 与所选服务一起使用的数据库引擎。 |
| databaseUser | string | dbadmin | 数据库管理员用户名。默认为 'dbadmin'。 |
| databaseName | string | - | 初始数据库名称。默认为项目名称。 |
| framework | prisma | prisma | 用于生成项目的 ORM 框架。 |
| iac | inherit | cdk | terraform | inherit | 首选的 IaC 提供商。默认情况下,这继承自您的初始选择。 |
| preferInstallDependencies | boolean | true | 是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。 |
生成器将在 <directory>/<name> 目录中创建以下项目结构:
文件夹prisma
文件夹models
- example.prisma Example model definition
- schema.prisma Main Prisma schema (references models)
文件夹src
- index.ts Project entry point
- prisma.ts Prisma runtime client wrapper
- utils.ts Runtime config and secret helpers
- create-db-user-handler.ts Lambda handler used to create the application database user during deployment
- migration-handler.ts Lambda handler used to run database migrations during deployment
- .gitignore Git ignore entries including generated Prisma client output
- config.json Local development connection details and runtime config key
- Dockerfile Container image definition for the migration handler
- package.json Project manifest defining the project’s package name and dependencies
- project.json Project configuration and build targets
- prisma.config.ts Configuration for Prisma CLI
本地开发脚本在所有数据库项目之间共享,并生成到 packages/common/scripts/ 中:
文件夹packages/common/scripts/src/rdb
- pull-image.ts Pulls the database container image
- start-container.ts Starts a local database container
- wait-for-postgres-db.ts Waits for the local database to be ready (PostgreSQL)
- wait-for-mysql-db.ts Waits for the local database to be ready (MySQL)
由于此生成器根据您选择的 iac 提供基础设施即代码,它将在 packages/common 中创建一个项目,其中包含相关的 CDK 构造或 Terraform 模块。
通用基础设施即代码项目的结构如下:
文件夹packages/common/constructs
文件夹src
文件夹app/ Constructs for infrastructure specific to a project/generator
- …
文件夹core/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
文件夹packages/common/terraform
文件夹src
文件夹app/ Terraform modules for infrastructure specific to a project/generator
- …
文件夹core/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
文件夹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 引擎类型不同。
生成的项目使用 Prisma ORM 来定义您的数据库架构并生成类型安全的客户端。工作流程是模型优先的:在数据库项目的 prisma/models/ 目录下添加或更新 Prisma 模型文件,然后从这些模型更改生成迁移。
示例 User 模型:
model User { id Int @id @default(autoincrement()) firstName String lastName String}有关更多详细信息,请参阅官方 Prisma 数据建模指南。
生成数据库客户端
Section titled “生成数据库客户端”生成器会自动配置 generate 目标,以便在构建项目时创建类型安全的 TypeScript Prisma 客户端。客户端被写入 generated/prisma(已添加到 .gitignore)。
您也可以随时手动生成客户端:
pnpm nx run <your-db-project-name>:generateyarn nx run <your-db-project-name>:generatenpx nx run <your-db-project-name>:generatebunx nx run <your-db-project-name>:generate使用 prisma 目标从工作区根目录运行 Prisma CLI 命令:
pnpm nx run <project>:prisma generateyarn nx run <project>:prisma generatenpx nx run <project>:prisma generatebunx nx run <project>:prisma generatesrc/prisma.ts 中的运行时包装器导出:
getPrisma()- 从 AWS AppConfig 加载数据库连接设置,并使用 IAM 身份验证创建 Prisma 客户端
客户端自动:
- 使用
RUNTIME_CONFIG_APP_ID环境变量从 AWS AppConfig 检索数据库配置 - 通过 AWS RDS Signer 生成临时身份验证令牌以进行 IAM 身份验证
- 使用证书验证管理 SSL/TLS 连接
- 通过持久数据库连接池处理连接池
在 prisma/models/ 下添加或更新模型后,使用 migrate dev 生成迁移文件并同时将它们应用到本地数据库。
生成的 prisma 目标在运行前会自动启动本地数据库容器:
pnpm nx run <project>:prisma migrate devyarn nx run <project>:prisma migrate devnpx nx run <project>:prisma migrate devbunx nx run <project>:prisma migrate dev如果您只想生成迁移文件而不将它们应用到本地数据库,请添加 --create-only:
pnpm nx run <project>:prisma migrate dev --create-onlyyarn nx run <project>:prisma migrate dev --create-onlynpx nx run <project>:prisma migrate dev --create-onlybunx nx run <project>:prisma migrate dev --create-only每次架构更改时,这会在 prisma/migrations 中生成一个新的迁移文件夹:
文件夹prisma
文件夹migrations
文件夹20260405013911_initial_migrations
- migration.sql
- migration_lock.toml
- schema.prisma
当您部署 AWS 堆栈时,生成的基础设施会自动将生成的迁移应用到已部署的数据库。
应用现有迁移
Section titled “应用现有迁移”当您拉取其他开发人员创建的迁移文件时,使用 migrate deploy 将这些现有迁移应用到本地数据库。
pnpm nx run <project>:prisma migrate deployyarn nx run <project>:prisma migrate deploynpx nx run <project>:prisma migrate deploybunx nx run <project>:prisma migrate deploy在此本地开发流程中,migrate deploy 将迁移文件应用到本地数据库;它不会将数据库部署到 AWS。
运行 Prisma 命令
Section titled “运行 Prisma 命令”生成的 prisma 目标公开了 Prisma CLI,因此您可以使用它对本地数据库运行 Prisma 支持的任何命令。有关可用命令,请参阅 Prisma CLI 参考。
pnpm nx run <project>:prisma <prisma-command>yarn nx run <project>:prisma <prisma-command>npx nx run <project>:prisma <prisma-command>bunx nx run <project>:prisma <prisma-command>使用 Prisma Studio
Section titled “使用 Prisma Studio”Prisma Studio 是本地数据库的可视化编辑器。使用它可以浏览表、检查和编辑记录、过滤数据、跟踪关系,并通过内置的 SQL 控制台运行原始 SQL。它对于在开发期间验证迁移和填充测试数据很有用。使用以下命令启动它:
pnpm nx run <project>:prisma studioyarn nx run <project>:prisma studionpx nx run <project>:prisma studiobunx nx run <project>:prisma studio停止本地数据库
Section titled “停止本地数据库”停止 dev(例如使用 Ctrl+C)会自动删除本地数据库容器,但保留命名卷,以便您的数据在重启后保持不变。
连接到数据库
Section titled “连接到数据库”在任何 TypeScript 项目中,从您的数据库包导入 getPrisma 并调用它以获取类型安全的 Prisma 客户端:
import { getPrisma } from '@my-scope/db';
const prisma = await getPrisma();const users = await prisma.user.findMany({ orderBy: { id: 'asc' } });getPrisma() 返回一个延迟初始化的缓存客户端。在同一个 Lambda 执行上下文中的后续调用会重用现有的连接池,而不是打开新的连接池。
Prisma 客户端公开从您的 prisma/models/ 架构派生的完全类型化的模型,为您提供从数据库到 API 响应的端到端类型安全。
getPrisma() 在运行时从 AWS AppConfig 获取数据库连接设置。
部署您的数据库
Section titled “部署您的数据库”关系数据库生成器会根据您选择的 iac 创建 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, } }); }}这将配置一个带有 RDS Proxy、管理员凭证、应用程序数据库用户、运行时配置注册和迁移处理程序的 Aurora 集群。
生成的基础设施会创建两个数据库用户:
- 管理员用户 - 在集群配置期间创建,凭证存储在 AWS Secrets Manager 中
- 应用程序用户 - 通过 Lambda 自定义资源创建,启用 IAM 身份验证,并在应用程序数据库上具有 DML 权限(SELECT、INSERT、UPDATE、DELETE)
Terraform 模块在 common/terraform 中创建。使用示例:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database"
# Database subnets have no internet route; Lambda subnets need NAT egress. vpc_id = aws_vpc.main.id database_subnet_ids = aws_subnet.database[*].id lambda_subnet_ids = aws_subnet.private[*].id
tags = local.common_tags}这将配置一个带有 RDS Proxy、管理员凭证、create-db-user Lambda、运行时配置注册、迁移 Lambda 和容器注册表资源的 Aurora 集群。
数据库模块在 database 运行时配置命名空间下注册其连接详细信息。在实例化共享运行时配置 AppConfig 应用程序时包含此命名空间:
module "runtime_config_appconfig" { source = "../../common/terraform/src/core/runtime-config/appconfig"
application_name = "my-app-runtime-config" namespaces = ["connection", "agentcore", "database"]}生成的基础设施会创建两个数据库用户:
- 管理员用户 - 在集群配置期间创建,凭证存储在 AWS Secrets Manager 中
- 应用程序用户 - 通过 Lambda 函数创建,启用 IAM 身份验证,并在应用程序数据库上具有 DML 权限(SELECT、INSERT、UPDATE、DELETE)
应用程序用户会自动创建,具有随机名称和 IAM 身份验证。生成的数据库客户端已配置为使用短期 RDS 令牌以此用户身份进行身份验证,因此您的应用程序代码永远不会处理数据库密码。
您的 VPC 应包括公有子网、具有出口的私有子网和私有隔离子网。数据库可以在私有隔离子网中运行,而应用程序 Lambda 函数应在具有出口的私有子网中运行,以便它们可以访问 AWS 服务(如 AppConfig)。
VPC 配置示例
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, }, ],});data "aws_availability_zones" "available" { state = "available"}
resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" enable_dns_hostnames = true enable_dns_support = true}
# Isolated subnets for the database: no route to the internetresource "aws_subnet" "database" { count = 2 vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index) availability_zone = data.aws_availability_zones.available.names[count.index]}
# Private subnets with NAT egress for Lambda functions and runtimes,# so they can reach AWS services such as AppConfigresource "aws_subnet" "private" { count = 2 vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 2) availability_zone = data.aws_availability_zones.available.names[count.index]}
# Public subnet hosting the NAT gatewayresource "aws_subnet" "public" { vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, 4) availability_zone = data.aws_availability_zones.available.names[0]}
resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id}
resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id
route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.main.id }}
resource "aws_route_table_association" "public" { subnet_id = aws_subnet.public.id route_table_id = aws_route_table.public.id}
resource "aws_eip" "nat" { domain = "vpc"}
resource "aws_nat_gateway" "main" { allocation_id = aws_eip.nat.id subnet_id = aws_subnet.public.id depends_on = [aws_internet_gateway.main]}
resource "aws_route_table" "private" { vpc_id = aws_vpc.main.id
route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.main.id }}
resource "aws_route_table_association" "private" { count = 2 subnet_id = aws_subnet.private[count.index].id route_table_id = aws_route_table.private.id}使用 connection 生成器将项目连接到此数据库 — 请参阅相关计算类型(例如 FastAPI、MCP 服务器、代理)的连接指南,了解访问数据库所需的基础设施配置。
为此项目构建的 Docker 镜像可以使用 Trivy 进行漏洞扫描,该工具从 ECR 托管的 Trivy 镜像运行。
项目中会添加一个 trivy 目标,用于扫描构建的镜像,如果发现任何 HIGH 或 CRITICAL 严重级别的漏洞,将以非零状态退出。生成的 Dockerfile 使用的基础镜像在生成时没有已知的可修复漏洞(这些严重级别),并升级捆绑的工具(如 npm)以保持这种状态。
扫描使用与镜像构建相同的容器引擎(docker 或 finch),因此不需要额外的工具。由于扫描仅在镜像更改时重新运行,未更改的镜像不会被重新扫描。提供的 trivy 根脚本会扫描工作区中的每个镜像:
pnpm trivyyarn trivynpm run trivybun trivy抑制 Trivy 发现
Section titled “抑制 Trivy 发现”在某些情况下,您可能希望抑制特定的漏洞,例如当尚无可用修复且您已评估风险为可接受时。
将漏洞 ID(每行一个)添加到项目根目录中的 .trivyignore 文件(即 project.json 旁边):
# node-tar arbitrary file write - not exploitable in our usageCVE-2024-XXXXX有关过滤发现的更多详细信息,请参阅 Trivy 过滤文档。
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 要求”当直接连接到 Aurora 集群(不使用 RDS Proxy)时,调用 getPrisma() 的运行时必须信任 Amazon RDS CA 捆绑包。生成的 Prisma 客户端启用证书验证;如何使 CA 捆绑包可用取决于连接到数据库的运行时。
对于 Amazon RDS,使用来自以下位置的全局 CA 捆绑包:
https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem运行时容器镜像
Section titled “运行时容器镜像”如果您为运行时准备自己的容器镜像,请在 Dockerfile 中下载 RDS CA 捆绑包并将其添加到操作系统信任存储。
RUN curl -fsSL "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" \ -o /etc/pki/ca-trust/source/anchors/rds-bundle.pem && \ update-ca-trustRUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \ rm -rf /var/lib/apt/lists/* && \ curl -fsSL "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" \ -o /usr/local/share/ca-certificates/rds-bundle.crt && \ update-ca-certificates压缩的 Lambda 函数
Section titled “压缩的 Lambda 函数”对于使用 Node.js 20 或更高版本运行时的压缩 Lambda 函数,通过设置 NODE_EXTRA_CA_CERTS 来加载 Amazon RDS CA 捆绑包:
const api = new Api(this, 'Api', { integrations: Api.defaultIntegrations(this) .withDefaultOptions({ environment: { NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem', }, }) .build(),});module "api" { source = "..." ...
environment_variables = { NODE_EXTRA_CA_CERTS = "/var/runtime/ca-cert.pem" }}有关更多详细信息,请参阅 AWS Lambda Amazon RDS 连接的 SSL/TLS 要求。使用 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 “日志记录和监控”postgresql 日志会导出到 Aurora PostgreSQL,日志记录范围仅限于 DDL 语句(log_statement=ddl),因此永远不会记录语句参数值——只要每个语句单独发送。log_statement=ddl 会逐字记录多语句批处理的整个原始文本(例如单个 psql -c "a;b;c" 调用),如果其中任何语句是 DDL,则包括同一批处理中的任何 DML 值。
对于 Aurora MySQL,会导出 audit 和 error 日志——故意排除了 general 和 slowquery,因为它们会记录完整的语句文本,包括 DML 值。高级审计的范围限定为连接和 DDL(server_audit_events=CONNECT,QUERY_DDL),因此永远不会记录语句参数值。
Performance Insights 默认在 Aurora 写入器实例上启用(使用集群的 KMS 密钥加密)。Aurora 引擎日志也默认导出到 CloudWatch Logs,配置为显示架构级活动而不泄露行数据。
如果不需要,可以按数据库禁用日志导出:
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableCloudwatchLogs: false, enablePerformanceInsights: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_cloudwatch_logs = false # disable if not required 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}MySQL: API Gateway 流式模式
Section titled “MySQL: API Gateway 流式模式”当将 Aurora MySQL 与 API Gateway 流式响应一起使用时(例如使用 tRPC 的 httpBatchStreamLink),Prisma MySQL 客户端在查询完成后会占用 Node.js 事件循环,从而阻止 Lambda 刷新流并结束请求。
要解决此问题,请在每次查询后在 finally 块中显式断开客户端连接,以便事件循环可以自由退出并且流式响应可以完成。
选项 1:每个过程
export const listExampleTable = publicProcedure .output(z.array(ExampleTableSchema)) .query(async () => { const prisma = await getPrisma(); try { return await prisma.exampleTable.findMany(); } finally { await prisma.$disconnect(); } });选项 2:tRPC 中间件
如果您使用的是中间件模式,请将 $disconnect() 调用添加到中间件,以便基于它构建的所有过程都会自动覆盖:
import { getPrisma } from '@my-scope/db';import { initTRPC } from '@trpc/server';
export interface IDbContext { db: Awaited<ReturnType<typeof getPrisma>>;}
export const createDbPlugin = () => { const t = initTRPC.context<IDbContext>().create(); return t.procedure.use(async (opts) => { const db = await getPrisma(); try { return await opts.next({ ctx: { ...opts.ctx, db, }, }); } finally { await db.$disconnect(); } });};MySQL: IAM 令牌过期
Section titled “MySQL: IAM 令牌过期”RDS IAM 身份验证令牌在 15 分钟后过期。MySQL Prisma 客户端在调用 getPrisma() 时将 IAM 令牌捕获为静态值。现有的打开连接不受影响,但如果在令牌过期后需要建立新连接,身份验证将失败。PostgreSQL 适配器通过在池每次打开新连接时动态刷新令牌来避免这种情况,但 MySQL 适配器没有等效机制。
对于长时间运行的任务(如批处理作业或数据迁移),请在每个工作单元开始时调用 getPrisma(),而不是为整个操作调用一次。因为 getPrisma() 总是为 MySQL 创建一个新客户端并获取新的 IAM 令牌,这确保每个连接都使用有效的令牌进行身份验证。
使用 connection 生成器将此项目与工作区中的其他项目集成。以下连接涉及此项目: