8.5 KiB
PDM — Physical Data Model —
| Version | 1.0 |
| Date | YYYY-MM-DD |
| Author | (skill sa-2-architecture) |
| Status | 🟡 Draft |
| Approved by | Tech Lead: — · DBA: — · BE Lead: — |
| Source | DAT_… v1.0 · DOM_… v1.0 · SRS_… §2.3.3 (bảng field) · BR_… của BA · SEC_… §5 |
| Scope | (kho nào — một PDM mỗi kho vật lý, hoặc một file nhiều §2.x) |
| Confidence | 🟡 |
Change Log
| Version | Date | Người sửa | Thay đổi | ADR / MIG |
|---|---|---|---|---|
| 1.0 | Bản đầu | MIG-001 |
Thẩm quyền: file DDL trong
02-architecture/schema/thắng bảng ở đây khi lệch — bảng là bản đọc cho người, DDL là thứ chạy. Lệch ⇒ lỗi tài liệu, sửa bảng.Vì sao có tài liệu này:
DATdừng ở "thực thể, quan hệ, ai sở hữu". Không cóPDM, mỗi dev tự đặt kiểu cột, độ dài, nullable, index — và bảng field của BA (FLD-…) chặn ở tầng UI nhưng không chặn ở tầng DB, hoặc ngược lại.
1. Kho và quy ước
| Kho | (tên · loại · phiên bản, ví dụ PostgreSQL 16 · RDS) — quyết định ở DAT §3 / ADR-nnn |
| Schema / namespace | (schema-per-module theo ADR-nnn: identity, catalog, cart_order…) |
| Công cụ migration | (Flyway / Liquibase / Prisma Migrate / Alembic / golang-migrate…) — ADR-nnn |
| Đặt tên | bảng snake_case số ít · PK id · FK <bảng>_id · index ix_<bảng>_<cột> · unique ux_… · FK constraint fk_<bảng>_<cột> |
| Kiểu id | uuid v7 / bigint identity — ADR-nnn; truyền qua API dạng string (ICD §1) |
| Thời gian | timestamptz, lưu UTC; cột created_at, updated_at bắt buộc mọi bảng |
| Tiền | numeric(18,2) + cột currency char(3) hoặc value object cố định VND — theo DOM §2 Money |
| Xoá | soft delete (deleted_at) cho bảng có yêu cầu retention ở DAT §5; hard delete cho bảng còn lại — ghi từng bảng ở §2 |
| Ký tự | UTF-8; độ dài varchar(n) tính theo code point, khớp bảng field của SRS (W3) |
2. Bảng — TBL-nnn
Một mục mỗi bảng. Mỗi bảng phải truy về một thực thể DAT §1 và một class DOM §2; bảng không
truy được là bảng thừa hoặc thiếu mô hình.
2.1 TBL-001 · cart_order.order ← Order (DAT §1.3 · DOM §2.1)
| Chủ sở hữu | CMP-04 — chỉ component này được ghi (DAT §1) |
| Ước lượng | … bản ghi/năm 1 · … năm 3 (DAT §2.2) · tăng …/tháng |
| Xoá | soft delete · retention … năm (DAT §5) |
| Phân mảnh | không / theo placed_at tháng (DAT §7.4 · ADR-nnn) |
Cột
| Cột | Kiểu | Null | Default | Ràng buộc | PII (SEC §5) |
Nguồn (FLD/BR) |
Ghi chú |
|---|---|---|---|---|---|---|---|
id |
uuid |
✗ | gen_uuid_v7() |
PK | — | — | |
order_number |
varchar(20) |
✗ | — | ux_order_order_number |
— | BR-010 định dạng |
khoá nghiệp vụ |
customer_id |
uuid |
✓ | NULL |
(không FK vật lý — khác schema, DAT §1) |
🔶 gián tiếp | FLD-SCR04-01 |
null = Guest |
total_amount |
numeric(18,2) |
✗ | — | CHECK (total_amount >= 0) |
— | BR-014 |
= Σ order_seller.subtotal_amount |
status |
varchar(32) |
✗ | 'pending' |
CHECK (status IN (…)) theo BR §3 |
— | BR-021 |
enum ở tầng app, CHECK ở DB |
idempotency_key |
varchar(64) |
✗ | — | ux_order_idempotency_key |
— | ADR-004 |
khoá của POST /v1/checkout |
placed_at |
timestamptz |
✗ | now() |
— | |||
created_at / updated_at |
timestamptz |
✗ | now() |
— | quy ước §1 | ||
deleted_at |
timestamptz |
✓ | NULL |
— | quy ước §1 | soft delete |
🔴 Bốn ô không được trống ở bất kỳ cột nào: kiểu có độ dài/độ chính xác · Null · Default · Nguồn. Trùng nguyên tắc "bảng ràng buộc cụ thể tới mức không cần hỏi lại" của SRS PART 2.
Index và khoá ngoại
| Tên | Loại | Cột | Vì sao (QAS/truy vấn DAT §7.1) |
Kích cỡ ước lượng |
|---|---|---|---|---|
ix_order_customer_placed |
btree | (customer_id, placed_at DESC) |
lịch sử đơn · QAS-006 |
|
fk_order_seller_order |
FK | order_seller.order_id → order.id |
ON DELETE RESTRICT |
🔴 Index không truy về truy vấn nào ⇒ bỏ. Truy vấn trong DAT §7.1 không có index ⇒ thiếu.
2.2 TBL-002 · <schema>.<bảng> ← <Entity>
(cùng cấu trúc)
3. Ánh xạ thực thể → bảng
Bảng đối chiếu bắt buộc, sa-conformance đọc bảng này.
Thực thể (DAT §1) |
Class (DOM §2) |
Bảng (TBL) |
Quan hệ 1 thực thể → n bảng? | Ghi chú |
|---|---|---|---|---|
Order |
Order |
TBL-001 |
1→1 | |
Order × Seller |
OrderSeller |
TBL-002 |
tách theo ADR-003 |
|
Cart (Redis) |
Cart |
(không phải bảng — key schema §5) |
Thực thể không có dòng ⇒ 🔴 chặn AG2. Bảng không có thực thể ⇒ bảng thừa hoặc thiếu mô hình.
4. DDL và migration — MIG-nnn
Vị trí: sa-output/<PROJECT>/02-architecture/schema/<kho>/
schema/<kho>/
├── V001__init_<schema>.sql ← MIG-001: toàn bộ bảng §2, chạy được từ CSDL rỗng
├── V001__init_<schema>.down.sql ← rollback tương ứng (bắt buộc)
├── V002__<thay-doi>.sql ← mỗi thay đổi sau baseline một cặp up/down
├── V002__<thay-doi>.down.sql
└── seed/
└── R__reference_data.sql ← dữ liệu tham chiếu (enum bảng, cấu hình) — idempotent
MIG |
File | Nội dung | Rollback | Dữ liệu phát sinh trong lúc chạy | Thời lượng ước lượng | Chạy trên |
|---|---|---|---|---|---|---|
MIG-001 |
V001__init_cart_order.sql |
tạo TBL-001..0nn |
V001__….down.sql drop ngược thứ tự FK |
không (CSDL rỗng) | < 1 phút | dev/stg/prod |
MIG-002 |
🔴 Migration không có down là migration một chiều (DAT §8). Với migration đổi dữ liệu
(không chỉ DDL) phải ghi thêm: cách đối chiếu sau khi chạy, ngưỡng chênh lệch chấp nhận, ai duyệt.
Quy ước file SQL: một câu lệnh một dòng logic · comment đầu file ghi MIG-nnn, TBL liên quan,
ADR · không dùng lệnh phụ thuộc quyền superuser · CREATE … IF NOT EXISTS chỉ trong seed.
Kiểm bằng máy (người điều phối chạy, ghi kết quả vào đây):
| Kiểm | Lệnh | Kết quả |
|---|---|---|
| Up từ rỗng | <tool> migrate trên container CSDL rỗng |
☐ |
| Down toàn bộ rồi up lại | <tool> migrate down --all && <tool> migrate |
☐ |
| Mọi bảng §2 có trong DDL | grep -c "CREATE TABLE" V001*.sql = số TBL |
☐ |
Mọi cột PII có cờ ở SEC §5 |
đối chiếu cột 🔶/✅ PII với SEC §5 |
☐ |
5. Kho không quan hệ (nếu có — cache, document, search)
| Kho | Key / collection | Cấu trúc value | TTL | Invalidation (DAT §7.4) |
Kích cỡ ước lượng |
|---|---|---|---|---|---|
Redis CMP-15 |
cart:{sessionId} |
JSON CartSnapshot (DOM §2) |
7 ngày | write-through khi PATCH/DELETE |
≤ 50 dòng × … |
6. Dữ liệu tham chiếu và seed
| Bảng | Nguồn dữ liệu | Ai duy trì | Cách nạp | Idempotent |
|---|
7. Đối chiếu
| Kiểm | Kết quả | Hành động |
|---|---|---|
DAT thực thể → TBL (§3) |
n/n | |
FLD-* trong SRS PART 2 → cột (kiểu/độ dài/null khớp) |
n/n | lệch ⇒ OQ, BA cập nhật SRS hoặc PDM sửa |
Cột PII → SEC §5 có dòng |
n/n | |
Truy vấn DAT §7.1 → index |
n/n | |
Mọi MIG có down |
n/n |
8. Giả định & Ngoài phạm vi
Giả định:
| ID | Giả định | Cách xác minh | Nếu sai |
|---|
Ngoài phạm vi:
- (ví dụ: không thiết kế kho phân tích/BI — ngoài
CON-…)
9. Open Questions
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì | Hệ quả nếu trả lời ngược |
|---|