Cơ sở dữ liệu quan hệ TypeScript
Generator này tạo một dự án cơ sở dữ liệu quan hệ mới được hỗ trợ bởi Amazon Aurora (PostgreSQL hoặc MySQL) và Prisma ORM. Nó tạo ra mã ứng dụng và cơ sở hạ tầng cần thiết để cung cấp và quản lý cơ sở dữ liệu bằng AWS CDK hoặc Terraform, với định nghĩa schema khai báo, triển khai migration tự động và một ORM client an toàn về kiểu.
Cách sử dụng
Phần tiêu đề “Cách sử dụng”Tạo một Cơ sở dữ liệu quan hệ
Phần tiêu đề “Tạo một Cơ sở dữ liệu quan hệ”Bạn có thể tạo một dự án cơ sở dữ liệu quan hệ mới theo hai cách:
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#rdbBạn cũng có thể thực hiện chạy thử để xem những tệp nào sẽ bị thay đổi
pnpm nx g @aws/nx-plugin:ts#rdb --dry-runyarn nx g @aws/nx-plugin:ts#rdb --dry-runnpx nx g @aws/nx-plugin:ts#rdb --dry-runbunx nx g @aws/nx-plugin:ts#rdb --dry-run- Cài đặt Nx Console VSCode Plugin nếu bạn chưa cài đặt
- Mở Nx Console trong VSCode
- Nhấp
Generate (UI)trong phần "Common Nx Commands" - Tìm kiếm
@aws/nx-plugin - ts#rdb - Điền các tham số bắt buộc
- Nhấp
Generate
Tùy chọn
Phần tiêu đề “Tùy chọn”| Tham số | Kiểu | Mặc định | Mô tả |
|---|---|---|---|
| name Bắt buộc | string | - | Tên của dự án cơ sở dữ liệu cần tạo |
| directory | string | packages | Thư mục để lưu trữ ứng dụng. |
| subDirectory | string | - | Thư mục con nơi dự án được đặt. Mặc định là tên dự án. |
| infra | aurora | none | aurora | Dịch vụ cơ sở dữ liệu quan hệ cần cung cấp. |
| engine | postgres | mysql | postgres | Database engine sử dụng với dịch vụ đã chọn. |
| databaseUser | string | dbadmin | Tên người dùng quản trị cơ sở dữ liệu. Mặc định là 'dbadmin'. |
| databaseName | string | - | Tên cơ sở dữ liệu ban đầu. Mặc định là tên dự án. |
| framework | prisma | prisma | Framework ORM sử dụng cho dự án được tạo. |
| iac | inherit | cdk | terraform | inherit | Nhà cung cấp IaC ưu tiên. Mặc định giá trị này được kế thừa từ lựa chọn ban đầu của bạn. |
| preferInstallDependencies | boolean | true | Có nên cài đặt các dependencies sau khi generator chạy hay không. Đặt thành false để hoãn việc cài đặt khi chạy nhiều generator liên tiếp (việc cài đặt vẫn sẽ chạy nếu cần thiết để các generator tiếp theo có thể tính toán Nx project graph); cài đặt một lần vào cuối. |
Kết quả của Generator
Phần tiêu đề “Kết quả của Generator”Generator sẽ tạo cấu trúc dự án sau trong thư mục <directory>/<name>:
Thư mụcprisma
Thư mụcmodels
- example.prisma Example model definition
- schema.prisma Main Prisma schema (references models)
Thư mụcsrc
- 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
Các script phát triển cục bộ được chia sẻ trên tất cả các dự án cơ sở dữ liệu và được tạo vào packages/common/scripts/:
Thư mụcpackages/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)
Cơ sở hạ tầng
Phần tiêu đề “Cơ sở hạ tầng”Vì generator này cung cấp infrastructure as code dựa trên iac bạn đã chọn, nó sẽ tạo một dự án trong packages/common bao gồm các CDK constructs hoặc Terraform modules liên quan.
Dự án infrastructure as code chung được cấu trúc như sau:
Thư mụcpackages/common/constructs
Thư mụcsrc
Thư mụcapp/ Constructs for infrastructure specific to a project/generator
- …
Thư mụccore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Thư mụcpackages/common/terraform
Thư mụcsrc
Thư mụcapp/ Terraform modules for infrastructure specific to a project/generator
- …
Thư mụccore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
Thư mụcpackages/common/constructs/src
Thư mụcapp
Thư mụcdbs
- <name>.ts Cơ sở hạ tầng cụ thể cho cơ sở dữ liệu của bạn
Thư mụccore
Thư mụcrdb
- aurora.ts Construct Aurora database chung
Thư mụcpackages/common/terraform/src
Thư mụcapp
Thư mụcdbs
Thư mục<name>
- <name>.tf Module cụ thể cho cơ sở dữ liệu của bạn
Thư mụccore
Thư mụcrdb
Thư mụcaurora
- aurora.tf Module Aurora chung
Kiến trúc
Phần tiêu đề “Kiến trúc”Cơ sở dữ liệu được triển khai có kiến trúc như sau. Theo mặc định, một Amazon RDS Proxy đứng trước cụm Aurora để gộp các kết nối và kích hoạt xác thực IAM — xem Vô hiệu hóa RDS Proxy để biết phương án thay thế. Kiến trúc giống nhau cho dù bạn chọn engine PostgreSQL hay MySQL; chỉ có phiên bản Aurora engine là khác nhau.
Phát triển cục bộ
Phần tiêu đề “Phát triển cục bộ”Mô hình hóa dữ liệu
Phần tiêu đề “Mô hình hóa dữ liệu”Dự án được tạo sử dụng Prisma ORM để định nghĩa schema cơ sở dữ liệu của bạn và tạo một client an toàn về kiểu. Quy trình làm việc là model-first: thêm hoặc cập nhật các tệp model Prisma trong thư mục prisma/models/ của dự án cơ sở dữ liệu của bạn, sau đó tạo một migration từ những thay đổi model đó.
Ví dụ model User:
model User { id Int @id @default(autoincrement()) firstName String lastName String}Để biết thêm chi tiết, xem hướng dẫn mô hình hóa dữ liệu Prisma chính thức.
Tạo Database Client
Phần tiêu đề “Tạo Database Client”Generator tự động cấu hình target generate để tạo một Prisma client TypeScript an toàn về kiểu bất cứ khi nào bạn build dự án. Client được ghi vào generated/prisma (được thêm vào .gitignore).
Bạn cũng có thể tạo client thủ công bất cứ lúc nào:
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>:generateSử dụng target prisma để chạy các lệnh Prisma CLI từ thư mục gốc workspace:
pnpm nx run <project>:prisma generateyarn nx run <project>:prisma generatenpx nx run <project>:prisma generatebunx nx run <project>:prisma generateWrapper runtime trong src/prisma.ts xuất:
getPrisma()- tải cài đặt kết nối cơ sở dữ liệu từ AWS AppConfig và tạo một Prisma client sử dụng xác thực IAM
Client tự động:
- Lấy cấu hình cơ sở dữ liệu từ AWS AppConfig sử dụng biến môi trường
RUNTIME_CONFIG_APP_ID - Tạo token xác thực tạm thời qua AWS RDS Signer cho xác thực IAM
- Quản lý kết nối SSL/TLS với xác thực chứng chỉ
- Xử lý connection pooling thông qua các pool kết nối cơ sở dữ liệu bền vững
Tạo Migrations
Phần tiêu đề “Tạo Migrations”Sau khi thêm hoặc cập nhật các model trong prisma/models/, sử dụng migrate dev để tạo các tệp migration và áp dụng chúng vào cơ sở dữ liệu cục bộ của bạn cùng lúc.
Target prisma được tạo tự động khởi động một container cơ sở dữ liệu cục bộ trước khi chạy:
pnpm nx run <project>:prisma migrate devyarn nx run <project>:prisma migrate devnpx nx run <project>:prisma migrate devbunx nx run <project>:prisma migrate devNếu bạn chỉ muốn tạo các tệp migration mà không áp dụng chúng vào cơ sở dữ liệu cục bộ, thêm --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Điều này tạo một thư mục migration mới trong prisma/migrations mỗi khi schema của bạn thay đổi:
Thư mụcprisma
Thư mụcmigrations
Thư mục20260405013911_initial_migrations
- migration.sql
- migration_lock.toml
- schema.prisma
Khi bạn triển khai AWS stack, cơ sở hạ tầng được tạo tự động áp dụng các migration đã tạo vào cơ sở dữ liệu đã triển khai.
Áp dụng Migrations hiện có
Phần tiêu đề “Áp dụng Migrations hiện có”Khi bạn pull các tệp migration được tạo bởi các nhà phát triển khác, sử dụng migrate deploy để áp dụng các migration hiện có đó vào cơ sở dữ liệu cục bộ của bạn.
pnpm nx run <project>:prisma migrate deployyarn nx run <project>:prisma migrate deploynpx nx run <project>:prisma migrate deploybunx nx run <project>:prisma migrate deployTrong quy trình phát triển cục bộ này, migrate deploy áp dụng các tệp migration vào cơ sở dữ liệu cục bộ của bạn; nó không triển khai cơ sở dữ liệu lên AWS.
Chạy các lệnh Prisma
Phần tiêu đề “Chạy các lệnh Prisma”Target prisma được tạo cung cấp Prisma CLI, vì vậy bạn có thể sử dụng nó để chạy bất kỳ lệnh nào được Prisma hỗ trợ đối với cơ sở dữ liệu cục bộ. Xem tài liệu tham khảo Prisma CLI để biết các lệnh có sẵn.
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>Sử dụng Prisma Studio
Phần tiêu đề “Sử dụng Prisma Studio”Prisma Studio là một trình chỉnh sửa trực quan cho cơ sở dữ liệu cục bộ của bạn. Sử dụng nó để duyệt các bảng, kiểm tra và chỉnh sửa bản ghi, lọc dữ liệu, theo dõi các quan hệ và chạy SQL thô qua console SQL tích hợp. Nó hữu ích để xác minh migrations và seeding dữ liệu thử nghiệm trong quá trình phát triển. Khởi chạy nó bằng:
pnpm nx run <project>:prisma studioyarn nx run <project>:prisma studionpx nx run <project>:prisma studiobunx nx run <project>:prisma studioDừng Cơ sở dữ liệu cục bộ
Phần tiêu đề “Dừng Cơ sở dữ liệu cục bộ”Dừng dev (ví dụ: với Ctrl+C) tự động xóa container cơ sở dữ liệu cục bộ, nhưng giữ lại volume được đặt tên để dữ liệu của bạn tồn tại qua các lần khởi động lại.
Kết nối đến Cơ sở dữ liệu
Phần tiêu đề “Kết nối đến Cơ sở dữ liệu”Trong bất kỳ dự án TypeScript nào, import getPrisma từ package cơ sở dữ liệu của bạn và gọi nó để lấy một Prisma client an toàn về kiểu:
import { getPrisma } from '@my-scope/db';
const prisma = await getPrisma();const users = await prisma.user.findMany({ orderBy: { id: 'asc' } });getPrisma() trả về một client được khởi tạo lười biếng, được cache. Các lần gọi tiếp theo trong cùng một ngữ cảnh thực thi Lambda sử dụng lại connection pool hiện có thay vì mở một cái mới.
Prisma client cung cấp các model được typed đầy đủ được lấy từ schema prisma/models/ của bạn, mang lại cho bạn type safety từ đầu đến cuối từ cơ sở dữ liệu đến phản hồi API của bạn.
getPrisma() lấy cài đặt kết nối cơ sở dữ liệu từ AWS AppConfig tại runtime.
Triển khai Cơ sở dữ liệu của bạn
Phần tiêu đề “Triển khai Cơ sở dữ liệu của bạn”Trình tạo cơ sở dữ liệu quan hệ tạo ra cơ sở hạ tầng CDK hoặc Terraform dựa trên iac bạn đã chọn.
Construct CDK được tạo trong common/constructs. Ví dụ sử dụng:
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, } }); }}Điều này cung cấp một cụm Aurora với RDS Proxy, thông tin xác thực admin, người dùng cơ sở dữ liệu ứng dụng, đăng ký cấu hình runtime và trình xử lý migration.
Cơ sở hạ tầng được tạo ra tạo hai người dùng cơ sở dữ liệu:
- Người dùng Admin - Được tạo trong quá trình cung cấp cụm với thông tin xác thực được lưu trữ trong AWS Secrets Manager
- Người dùng Ứng dụng - Được tạo thông qua tài nguyên tùy chỉnh Lambda với xác thực IAM được bật và các đặc quyền DML (SELECT, INSERT, UPDATE, DELETE) trên cơ sở dữ liệu ứng dụng
Module Terraform được tạo trong common/terraform. Ví dụ sử dụng:
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}Điều này cung cấp một cụm Aurora với RDS Proxy, thông tin xác thực admin, Lambda create-db-user, đăng ký cấu hình runtime, Lambda migration và các tài nguyên container registry.
Module cơ sở dữ liệu đăng ký chi tiết kết nối của nó dưới namespace cấu hình runtime database, mà ứng dụng AppConfig cấu hình runtime được chia sẻ mặc định hiển thị.
Cơ sở hạ tầng được tạo ra tạo hai người dùng cơ sở dữ liệu:
- Người dùng Admin - Được tạo trong quá trình cung cấp cụm với thông tin xác thực được lưu trữ trong AWS Secrets Manager
- Người dùng Ứng dụng - Được tạo thông qua hàm Lambda với xác thực IAM được bật và các đặc quyền DML (SELECT, INSERT, UPDATE, DELETE) trên cơ sở dữ liệu ứng dụng
Người dùng ứng dụng được tự động tạo với tên ngẫu nhiên và xác thực IAM. Client cơ sở dữ liệu được tạo đã được cấu hình sẵn để xác thực với tư cách người dùng này bằng cách sử dụng token RDS có thời hạn ngắn, vì vậy mã ứng dụng của bạn không bao giờ xử lý mật khẩu cơ sở dữ liệu.
VPC của bạn nên bao gồm các subnet công khai, các subnet riêng tư có egress và các subnet riêng tư bị cô lập. Cơ sở dữ liệu có thể chạy trong các subnet riêng tư bị cô lập, trong khi các hàm Lambda ứng dụng nên chạy trong các subnet riêng tư có egress để chúng có thể truy cập các dịch vụ AWS như AppConfig.
Cấu hình VPC ví dụ
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}Sử dụng trình tạo connection để kết nối một dự án với cơ sở dữ liệu này — xem hướng dẫn kết nối cho loại compute liên quan (ví dụ: FastAPI, MCP server, agent) để biết cách kết nối cơ sở hạ tầng cần thiết để truy cập nó.
Quét Image
Phần tiêu đề “Quét Image”Docker image được xây dựng cho dự án này có thể được quét để tìm các lỗ hổng bảo mật bằng cách sử dụng Trivy, chạy từ ECR-hosted Trivy image.
Một target trivy được thêm vào dự án của bạn để quét image đã xây dựng và thoát với mã khác không nếu phát hiện bất kỳ lỗ hổng bảo mật mức độ nghiêm trọng HIGH hoặc CRITICAL nào. Dockerfile được tạo ra sử dụng một base image không có lỗ hổng bảo mật có thể sửa chữa nào ở các mức độ nghiêm trọng này tại thời điểm tạo, và nâng cấp các công cụ đi kèm (chẳng hạn như npm) để duy trì trạng thái đó.
Quá trình quét sử dụng cùng container engine với quá trình xây dựng image của bạn (docker hoặc finch), do đó không cần công cụ bổ sung nào. Vì quá trình quét chỉ được chạy lại khi image thay đổi, một image không thay đổi sẽ không được quét lại. Script root trivy được cung cấp sẽ quét mọi image trong workspace:
pnpm trivyyarn trivynpm run trivybun trivyLoại Bỏ Các Phát Hiện Của Trivy
Phần tiêu đề “Loại Bỏ Các Phát Hiện Của Trivy”Có thể có những trường hợp bạn muốn loại bỏ một lỗ hổng bảo mật cụ thể, ví dụ như khi chưa có bản sửa lỗi và bạn đã đánh giá rủi ro là có thể chấp nhận được.
Thêm ID lỗ hổng bảo mật (mỗi dòng một ID) vào file .trivyignore trong thư mục gốc của dự án (tức là bên cạnh project.json của bạn):
# node-tar arbitrary file write - not exploitable in our usageCVE-2024-XXXXXĐể biết thêm chi tiết về việc lọc các phát hiện, hãy tham khảo tài liệu lọc của Trivy.
Cấu hình RDS Proxy
Phần tiêu đề “Cấu hình RDS Proxy”Cơ sở hạ tầng được tạo ra bao gồm một RDS Proxy theo mặc định, nằm giữa ứng dụng của bạn và cụm Aurora. RDS Proxy cung cấp một số lợi ích:
- Connection pooling - Duy trì một nhóm các kết nối cơ sở dữ liệu có thể được chia sẻ giữa các phiên bản ứng dụng, giảm chi phí thiết lập kết nối mới
- Connection resilience - Tự động xử lý chuyển đổi dự phòng và kết nối lại trong quá trình thay thế hoặc bảo trì phiên bản Aurora
- IAM authentication - Hỗ trợ xác thực cơ sở dữ liệu dựa trên IAM, loại bỏ nhu cầu quản lý thông tin xác thực cơ sở dữ liệu trong mã ứng dụng của bạn
- Improved security - Thực thi mã hóa TLS cho tất cả các kết nối
Tắt RDS Proxy
Phần tiêu đề “Tắt RDS Proxy”Bạn có thể tắt RDS proxy như sau:
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableRdsProxy: false,});Khi RDS Proxy bị tắt, ứng dụng của bạn kết nối trực tiếp đến điểm cuối cụm Aurora.
Theo mặc định, RDS Proxy được bật. Bạn có thể tắt nó nếu cần:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_rds_proxy = false}Khi RDS Proxy bị tắt, ứng dụng của bạn kết nối trực tiếp đến điểm cuối cụm Aurora.
Yêu cầu SSL khi kết nối không có RDS Proxy
Phần tiêu đề “Yêu cầu SSL khi kết nối không có RDS Proxy”Khi kết nối trực tiếp đến Aurora cluster (không có RDS Proxy), runtime gọi getPrisma() phải tin tưởng Amazon RDS CA bundle. Prisma client được tạo bật xác minh chứng chỉ; cách bạn cung cấp CA bundle phụ thuộc vào runtime kết nối đến cơ sở dữ liệu.
Đối với Amazon RDS, sử dụng CA bundle toàn cầu từ:
https://truststore.pki.rds.amazonaws.com/global/global-bundle.pemRuntime Container Images
Phần tiêu đề “Runtime Container Images”Nếu bạn chuẩn bị container image của riêng mình cho runtime, tải xuống RDS CA bundle trong Dockerfile của bạn và thêm nó vào trust store của hệ điều hành.
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-certificatesZipped Lambda Functions
Phần tiêu đề “Zipped Lambda Functions”Đối với các Lambda function được nén sử dụng runtime Node.js 20 trở lên, tải Amazon RDS CA bundle bằng cách đặt NODE_EXTRA_CA_CERTS:
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" }}Để biết thêm chi tiết, xem yêu cầu SSL/TLS cho kết nối Amazon RDS của AWS Lambda. Khi sử dụng RDS Proxy, bạn không cần cấu hình RDS CA bundle trong runtime kết nối đến cơ sở dữ liệu.
Cluster Instances
Phần tiêu đề “Cluster Instances”Cấu hình các instance writer và reader cho Aurora cluster của bạn.
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}Serverless Capacity
Phần tiêu đề “Serverless Capacity”Kiểm soát giới hạn mở rộng của Aurora Serverless v2 để phù hợp với khối lượng công việc của bạn.
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}Engine Version
Phần tiêu đề “Engine Version”Cố định một phiên bản Aurora engine cụ thể.
Theo mặc định, image container cơ sở dữ liệu cục bộ được tạo ra sẽ khớp với phiên bản Aurora engine mặc định. Nếu bạn thay đổi phiên bản Aurora engine, bạn nên sử dụng phiên bản image container cục bộ tương ứng để đảm bảo khả năng tương thích tối đa. Xem ghi chú phát hành của AWS cho phiên bản Aurora PostgreSQL và phiên bản Aurora MySQL để xác định phiên bản cơ sở dữ liệu cộng đồng tương ứng.
Image cơ sở dữ liệu cục bộ được cấu hình trong trường localDev.image của tệp config.json được tạo ra trong thư mục gốc của dự án cơ sở dữ liệu của bạn. Cập nhật giá trị đó khi bạn thay đổi phiên bản engine.
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"}Deletion Protection
Phần tiêu đề “Deletion Protection”Cụm Aurora được bảo vệ bởi hai lớp bảo vệ độc lập, do đó việc tắt một trong hai không thể xóa dữ liệu của bạn:
deletionProtection, được thực thi bởi RDS.RemovalPolicy.RETAIN, được thực thi bởi CloudFormation, giữ cụm tại chỗ khi nó bị xóa khỏi stack.
deletion_protection, được thực thi bởi RDS.lifecycle { prevent_destroy = true }trên cụm trongcommon/terraform/src/core/rdb/aurora/aurora.tf, được thực thi bởi Terraform, làm thất bại bất kỳ kế hoạch nào có thể phá hủy cụm.
Xóa Cơ Sở Dữ Liệu
Phần tiêu đề “Xóa Cơ Sở Dữ Liệu”Bạn có thể tắt bảo vệ cho các môi trường mà việc xóa cơ sở dữ liệu được mong đợi, chẳng hạn như các stack phát triển hoặc xem trước có thời gian tồn tại ngắn.
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}prevent_destroy phải là một giá trị cố định — Terraform không cho phép nó tham chiếu đến một biến — do đó nó không thể được tắt từ main.tf. Đồng thời xóa khối lifecycle khỏi cụm trong common/terraform/src/core/rdb/aurora/aurora.tf:
resource "aws_rds_cluster" "database" { # ...
lifecycle { prevent_destroy = true }}Removal Policy
Phần tiêu đề “Removal Policy”Cấu trúc CDK giữ lại cụm Aurora theo mặc định (removalPolicy: RemovalPolicy.RETAIN). Thay đổi điều này khi bạn muốn việc xóa CDK stack tạo snapshot hoặc hủy cụm thay vì giữ lại.
Khi sử dụng RemovalPolicy.DESTROY, tính năng bảo vệ xóa cũng phải được tắt trước khi cụm có thể bị xóa.
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... removalPolicy: RemovalPolicy.SNAPSHOT,});Đối với môi trường tạm thời mà cơ sở dữ liệu nên được xóa cùng với stack:
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 không sử dụng chính sách xóa của CDK. Theo mặc định, module tạo một snapshot cuối cùng khi xóa (skip_final_snapshot = false). Để bỏ qua snapshot cuối cùng cho môi trường tạm thời:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}Logging và Monitoring
Phần tiêu đề “Logging và Monitoring”Log postgresql được xuất cho Aurora PostgreSQL, với phạm vi ghi log chỉ giới hạn ở các câu lệnh DDL (log_statement=ddl) do đó các giá trị tham số của câu lệnh không bao giờ được ghi log — miễn là mỗi câu lệnh được gửi riêng lẻ. log_statement=ddl ghi log toàn bộ văn bản thô của một batch nhiều câu lệnh (ví dụ: một lệnh gọi psql -c "a;b;c" duy nhất) nguyên văn nếu bất kỳ câu lệnh nào trong đó là DDL, bao gồm cả các giá trị DML trong cùng batch đó.
Các log audit và error được xuất cho Aurora MySQL — general và slowquery được cố ý loại trừ vì chúng ghi lại toàn bộ văn bản câu lệnh, bao gồm cả giá trị DML. Advanced Auditing được giới hạn phạm vi cho các kết nối và DDL (server_audit_events=CONNECT,QUERY_DDL), do đó các giá trị tham số câu lệnh không bao giờ được ghi log.
Performance Insights được bật trên Aurora writer instance theo mặc định (được mã hóa bằng KMS key của cluster). Aurora engine logs cũng được xuất sang CloudWatch Logs theo mặc định, được cấu hình để hiển thị hoạt động ở cấp độ schema mà không làm rò rỉ dữ liệu hàng.
Tắt xuất log cho từng database nếu không cần thiết:
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}Xoay vòng Encryption Key
Phần tiêu đề “Xoay vòng Encryption Key”Khóa KMS được sử dụng để mã hóa cụm Aurora và secret thông tin xác thực của nó có tính năng xoay vòng khóa tự động được bật theo mặc định. Tắt tính năng này nếu chính sách bảo mật của bạn quản lý việc xoay vòng từ bên ngoài.
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}Hạn chế
Phần tiêu đề “Hạn chế”MySQL: Chế độ Streaming API Gateway
Phần tiêu đề “MySQL: Chế độ Streaming API Gateway”Khi sử dụng Aurora MySQL với phản hồi streaming API Gateway (ví dụ: với httpBatchStreamLink của tRPC), Prisma MySQL client giữ event loop của Node.js sau khi một truy vấn hoàn thành, ngăn Lambda flush stream và kết thúc request.
Để giải quyết vấn đề này, ngắt kết nối client một cách rõ ràng trong một khối finally sau mỗi truy vấn để event loop tự do thoát và phản hồi streaming có thể hoàn thành.
Tùy chọn 1: theo procedure
export const listExampleTable = publicProcedure .output(z.array(ExampleTableSchema)) .query(async () => { const prisma = await getPrisma(); try { return await prisma.exampleTable.findMany(); } finally { await prisma.$disconnect(); } });Tùy chọn 2: tRPC middleware
Nếu bạn đang sử dụng mẫu middleware, thêm lời gọi $disconnect() vào middleware để tất cả các procedure được xây dựng trên nó được bao phủ tự động:
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: Hết hạn IAM Token
Phần tiêu đề “MySQL: Hết hạn IAM Token”Token xác thực IAM của RDS hết hạn sau 15 phút. Prisma MySQL client lưu giữ IAM token như một giá trị tĩnh tại thời điểm getPrisma() được gọi. Một kết nối mở hiện có không bị ảnh hưởng, nhưng nếu một kết nối mới cần được thiết lập sau khi token đã hết hạn, xác thực sẽ thất bại. Adapter PostgreSQL tránh điều này bằng cách làm mới token một cách động mỗi khi pool mở một kết nối mới, nhưng adapter MySQL không có cơ chế tương đương.
Đối với các tác vụ chạy lâu như batch job hoặc migration dữ liệu, gọi getPrisma() ở đầu mỗi đơn vị công việc thay vì một lần cho toàn bộ hoạt động. Bởi vì getPrisma() luôn tạo một client mới và lấy một IAM token mới cho MySQL, điều này đảm bảo mỗi kết nối xác thực với một token hợp lệ.
Kết nối
Phần tiêu đề “Kết nối”Sử dụng generator connection để tích hợp dự án này với các dự án khác trong workspace của bạn. Các kết nối sau liên quan đến dự án này: