Flyway Migration: Quản Trị Phiên Bản Schema Như Mã Nguồn
Thiết lập Flyway với Spring Boot, quản lý bảng flyway_schema_history, tính bất biến của checksum và cơ chế baseline cho cơ sở dữ liệu legacy.
TL;DR: Flyway biến schema cơ sở dữ liệu thành các artifact có thể quản lý bằng Git: mỗi thay đổi là một file SQL có định dạng V<version>__<description>.sql, được thực thi đúng một lần duy nhất theo thứ tự và lưu checksum vào bảng flyway_schema_history. Sau khi đã apply, file migration trở thành bất biến để bảo toàn tính nhất quán giữa các môi trường. Sử dụng ddl-auto: validate kết hợp cùng Flyway là chuẩn mực vàng cho production.
Vì sao ddl-auto=update bị cấm trên môi trường Production?
Cấu hình ddl-auto: update của Hibernate tiềm ẩn nhiều rủi ro phá hủy dữ liệu:
- Không có lịch sử phiên bản: Không thể biết database đang ở trạng thái nào.
- Không thể DROP hoặc RENAME: Khi đổi tên trường Java, Hibernate chỉ thêm cột mới và bỏ hoang cột cũ, gây rác schema.
- Xung đột đa tiến trình (Race Condition): Khi triển khai nhiều pod khởi động đồng thời, các pod cùng chạy
ALTER TABLEgây khóa bảng deadlock.
Flyway giải quyết triệt để vấn đề này theo 3 nguyên lý: Versioned (có số phiên bản tuần tự), Reproducible (chạy trên bất kỳ máy nào đều cho kết quả giống hệt nhau), và Audited (ghi vết rõ ràng).
Các khái niệm cốt lõi của Flyway gồm những gì?
1. Quy tắc đặt tên file Migration
Flyway phát hiện các file migration dựa trên tên file trong thư mục src/main/resources/db/migration/:
V<version>__<mo_ta>.sql
^ ^^
| Bat buoc 2 dau gach duoi (Double Underscore)
So version (1, 2, 2.1, 20260501...)
Tên file V1_init.sql (1 dấu gạch dưới) sẽ bị Flyway bỏ qua âm thầm mà không có cảnh báo nào, khiến schema không được tạo và Hibernate báo lỗi thiếu bảng.
2. Bảng theo dõi flyway_schema_history
Khi khởi chạy, Flyway tự động tạo bảng flyway_schema_history làm "sổ cái" theo dõi:
SELECT installed_rank, version, description, checksum, success
FROM flyway_schema_history;

Flyway so sánh danh sách file trên đĩa với bảng history:
- File nào đã có row thành công: Bỏ qua (Idempotent).
- File nào chưa có: Thực thi tuần tự và ghi nhận checksum tương ứng.
Tại sao mã Checksum bắt buộc phải bất biến?
Mỗi file migration khi chạy xong sẽ được tính toán một mã băm CRC32 checksum lưu vào database.
Nếu bạn sửa đổi dù chỉ một dấu cách trong file V1__init_schema.sql sau khi đã deploy, Flyway sẽ phát hiện mã checksum tính toán lại bị lệch so với mã đã lưu trong history và lập tức từ chối khởi động ứng dụng (Fail-Fast):

Nguyên tắc vàng: Không bao giờ sửa file migration cũ đã merge vào branch chính. Mọi sửa đổi, vá lỗi phải được viết trong một file migration mới (ví dụ: V2__fix_column.sql).
Cấu hình chuẩn mực trong Spring Boot ra sao?
Khai báo dependency trong pom.xml:
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>
Cấu hình trong application.yml:
spring:
flyway:
enabled: true
locations: classpath:db/migration
validate-on-migrate: true # Kiem tra checksum nghiem ngat khi boot
jpa:
hibernate:
ddl-auto: validate # Hibernate chi validate entity khop voi schema Flyway
Tích hợp Flyway vào Cơ sở dữ liệu cũ (Baseline) như thế nào?
Nếu database production đã có sẵn 20 bảng từ trước khi đưa Flyway vào dự án:
- Nếu để mặc định, Flyway không thấy bảng history nên sẽ chạy lại
V1__init_schema.sqlvà gây lỗirelation "projects" already exists. - Giải pháp: Bật tính năng Baseline.
spring:
flyway:
baseline-on-migrate: true # Tu dong danh dau moc ban dau neu DB chua co history
baseline-version: 1 # Coi nhu DB hien tai da o version 1
Khi đó:
- Trên Production: Flyway chèn một bản ghi BASELINE version 1 vào history mà không chạy file
V1, sau đó chỉ thực thi các file từV2trở đi. - Trên môi trường Dev/Test mới: Database trống hoàn toàn nên Flyway sẽ chạy tuần tự từ
V1đến hết, đảm bảo cả hai môi trường đạt cùng schema cuối cùng.
Những cạm bẫy phổ biến cần tránh là gì?
- Đặt sai tên file (1 dấu gạch dưới): Flyway bỏ qua file migration mà không hề báo lỗi cú pháp.
- Dùng song song ddl-auto=update với Flyway: Gây ra xung đột tranh chấp thay đổi cấu trúc bảng giữa Hibernate và Flyway.
- Sửa file migration đã commit lên Git: Làm hỏng tính toàn vẹn checksum và khiến toàn bộ cluster không thể khởi động.
Tự kiểm tra kiến thức
- Q1Tại sao Flyway lại kiểm tra nghiêm ngặt mã checksum và từ chối khởi động ứng dụng nếu phát hiện file migration cũ bị chỉnh sửa?
- Q2Định dạng tên file nào sau đây là hợp lệ để Flyway nhận diện được một file Versioned Migration?
- Q3Khi triển khai hệ thống trên Kubernetes với 10 pod cùng khởi động đồng thời, Flyway ngăn chặn xung đột chạy migration bằng cách nào?
- Q4Cặp cấu hình chuẩn mực nhất giữa Hibernate và Flyway trên môi trường Production là gì?
- Q5Tính năng 'baseline-on-migrate: true' trong Flyway giải quyết bài toán nào?
Bài tiếp theo: Chiến Lược Migration: Zero-Downtime và Mô Hình Expand-Contract
Bài này có giúp bạn hiểu bản chất không?
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Migration & Capstone — tổng quan
Bài tiếpChiến Lược Flyway: Zero-Downtime và Expand-Contract
Lộ trình Junior Java Backend Developer
Chặng 17/21 · Database migration (Flyway) — bài 1/2 của chặng
Thảo luận & góp ý
Hỏi đáp về bài này