Migration: Thay đổi Schema một cách an toàn
Schema của bạn sẽ thay đổi — bạn sẽ thêm một cột, đổi tên một bảng, thêm một chỉ mục (index). Hãy nghĩ về nó như các thay đổi được theo dõi trên một tài liệu dùng chung: mỗi thay đổi được ghi lại theo thứ tự, để bản sao của mọi người có thể được cập nhật theo cùng một cách. Một migration (di trú schema) là một đoạn script có phiên bản, có thể lặp lại, mô tả một thay đổi như vậy. Migration quan trọng vì schema trên laptop của bạn, laptop của đồng nghiệp, và production phải luôn giống hệt nhau.
Các quy tắc giữ cho migration an toàn:
- Không bao giờ chỉnh sửa cơ sở dữ liệu bằng tay trên production. Hãy viết một migration.
- Migration luôn tiến về phía trước. Mỗi cái là một tệp mới; bạn không viết lại các migration cũ đã chạy rồi.
- Cẩn thận với các thay đổi mang tính phá hủy. Xóa một cột hoặc một bảng sẽ xóa dữ liệu vĩnh viễn. Hãy sao lưu trước.
- Các thay đổi bổ sung (additive) là an toàn nhất. Thêm một cột có thể để trống (nullable) hiếm khi phá vỡ gì cả; đổi tên hoặc xóa một cột có thể làm hỏng code đang chạy.
Các migration tạo thành một chuỗi có thứ tự: mỗi cái là một bước được đánh số, đưa mọi bản sao của cơ sở dữ liệu từ một trạng thái đã biết sang trạng thái tiếp theo, để laptop của bạn, của đồng nghiệp, và production cuối cùng đều giống hệt nhau:
empty DB
│
▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ 001_init │ ▶ │ 002_add │ ▶ │ 003_index │ ▶ │ 004_bio │
│ users │ │ posts │ │ on author │ │ column │
└────────────┘ └────────────┘ └────────────┘ └────────────┘
apply in order ─────────────────────────────────────────▶ current
never edit a step that already ran — add a NEW one
Các công cụ như Prisma, Drizzle, hay Rails migrations tạo và theo dõi những thứ này giúp bạn. Hãy để chúng làm việc đó.
Một migration gồm hai nửa: thay đổi cần áp dụng (up) và cách hoàn tác nó (down). Một công cụ đáng tin cậy tạo ra cả hai, để một lần triển khai () tệ có thể được rollback (khôi phục lại) một cách gọn gàng:
-- up: add an optional bio, safe to apply live
ALTER TABLE users ADD COLUMN bio TEXT;
-- down: reverse it
ALTER TABLE users DROP COLUMN bio;
Những migration thực sự nguy hiểm là đổi tên và thay đổi kiểu dữ liệu, vì code cũ và schema mới sẽ tạm thời không khớp nhau. Cách làm chuyên nghiệp là tách chúng thành các bước bổ sung (additive): thêm cột mới, lấp đầy dữ liệu (backfill) cho nó, chuyển code sang đọc cột mới, và chỉ xóa cột cũ trong một lần deploy sau đó khi không còn gì tham chiếu tới nó nữa. Nghe có vẻ chậm, nhưng đó là sự khác biệt giữa một lần phát hành suôn sẻ và một đợt lỗi 500 dồn dập cho mọi người dùng ngay giữa lúc deploy.