# Flyway × Spring Boot:整合與使用指南(含版本管理觀念與實務流程) Flyway 是一套 **資料庫版本控管(Schema Migration)** 工具。 你可以把它想成「DB 的 Git log + 部署腳本管理」: * 每次 DB 結構變更(DDL)與必要資料(部分 DML)都用一個 **migration 檔**記錄 * Flyway 在啟動或部署時自動執行「尚未執行過」的 migration * DB 內會有一張歷史表追蹤版本與 checksum,避免環境漂移 --- ## 1. Flyway 解決什麼問題? ### 1.1 確保環境一致 同一套 migrations 在 dev/sit/uat/prod 跑出相同的 DB 結構(schema)。 ### 1.2 變更可追蹤、可審核 每個版本變更都是一個檔案,可 code review、可回溯原因。 ### 1.3 部署更可靠 部署時只要跑 Flyway,就能把 DB 從「目前版本」補到「最新版本」。 > Flyway 的設計偏向 **forward-only**:用新版本修正問題,而不是自由切換版本。 --- ## 2. Flyway 版本管理核心概念 ### 2.1 Migration 檔 = DB 版本 * `V1__init.sql` * `V2__add_user_table.sql` * `V3__add_index_on_user.sql` 命名規則(最常用的版本化 migration): ``` V<版本號>__<描述>.sql ``` ### 2.2 Flyway 會在 DB 建一張歷史表 預設表名:`flyway_schema_history` 表裡會記錄: * version / description * installed_on * checksum(避免你偷偷改已執行過的檔) * success/failure ### 2.3 啟動時會不會每次都從 V1 跑? * **第一次(全新 DB)**:會從 V1 跑到最新 * **之後每次啟動**:只跑「新加的版本」 --- ## 3. 在 Spring Boot 中整合 Flyway ### 3.1 加入依賴 **Maven** ```xml <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> </dependency> ``` **Gradle** ```gradle implementation 'org.flywaydb:flyway-core' ``` > 你的 JDBC driver(PostgreSQL/SQL Server/Oracle)通常本來就會有。 --- ### 3.2 放置 migrations 預設路徑: ``` src/main/resources/db/migration ``` 範例: `src/main/resources/db/migration/V1__init.sql` ```sql CREATE TABLE app_user ( id BIGINT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, created_at TIMESTAMP NOT NULL ); ``` `src/main/resources/db/migration/V2__add_last_login_at.sql` ```sql ALTER TABLE app_user ADD last_login_at TIMESTAMP NULL; ``` --- ### 3.3 application.yml 基本設定 ```yaml spring: flyway: enabled: true locations: classpath:db/migration ``` 只要你有設定 `spring.datasource.*`,Spring Boot 會在啟動時自動跑 Flyway。 --- ## 4. 常見進階設定(實務很常用) ### 4.1 舊資料庫接管(baseline) 如果你的 DB 已經有很多表,但以前不是 Flyway 管的,直接 migrate 可能被擋(schema 非空)。 ```yaml spring: flyway: baseline-on-migrate: true baseline-version: 1 ``` 含義: * 建立 `flyway_schema_history` * 把「現在」當作 baseline 起點 * 後續從更高版本開始管理 --- ### 4.2 指定只跑到某個版本(target) 你可以控制「最多 migrate 到哪個版本」,例如只跑到 V10: ```yaml spring: flyway: target: 10 ``` 使用情境: * 分階段上線(SIT/UAT 先追新,Prod 暫時停在某版) --- ### 4.3 Repeatable migrations(R__) 適合用在 View / Stored Procedure / Function 等會反覆更新的物件。 命名: ``` R__<描述>.sql ``` 例:`R__create_or_replace_views.sql` 特性: * 內容有變(checksum 變)→ 下次 migrate 會再跑 --- ### 4.4 多 schema / 自訂歷史表 ```yaml spring: flyway: schemas: app_schema table: flyway_schema_history ``` --- ## 5. 正常團隊流程:誰要動 DB 該怎麼做? ### 5.1 DDL(建表/加欄位/索引/約束) **一律新增 migration 檔**(不要手改正式 DB,也不要回頭改舊 migration)。 正確:新增 `V12__add_xxx.sql` 錯誤:改 `V1__init.sql` 或改已上線跑過的版本(checksum 會炸)。 --- ### 5.2 DML(資料)要不要用 migration 管? 分兩類: #### A) 測試資料 / 個人資料 * dev 手動增刪改 OK * 但不保證別人環境也有 #### B) 系統必要資料(seed data) 例如:SYS_SETTING、權限角色、字典資料、必要參數 * 建議用 migration 管 * 否則會發生「我本機正常、SIT/UAT 缺資料爆掉」 範例:`V5__seed_sys_setting.sql` ```sql INSERT INTO sys_setting (k, v) VALUES ('TOKEN_EXPIRE_MIN', '15'); ``` --- ## 6. 開發環境手動改 DB 會怎樣?(重要) ### 6.1 手動改 DDL 的風險 * 環境漂移:你本機 DB 跟別人不同 * 之後 migration 會撞到「欄位已存在」導致啟動失敗 **建議:DDL 不要手改,直接寫 migration。** ### 6.2 手動改資料的影響 * 測試資料:OK * 必要 seed:最好寫進 migration ### 6.3 本機亂掉的最乾淨解法 * 砍掉 dev DB(或清空 schema)重建 * 讓 Flyway 從 V1 跑到最新 > 正式環境通常不允許 clean;dev 可以用「重建 DB」解決。 --- ## 7. Flyway vs Hibernate ddl-auto * `ddl-auto=create/update`:方便但不可控、難審核、容易飄移 * Flyway:可控、可審核、可重播,較適合正式環境 常見配置: * 正式:Flyway 管 schema * JPA:`ddl-auto=validate` 或 `none` --- ## 8. 實務建議(讓團隊跑得穩) 1. **所有 DDL 都走 migration**(禁止手改正式 DB) 2. migration 一旦進環境就不要改內容(避免 checksum 問題) 3. 需要回滾: * 正式環境以備份還原最可靠 * 或新增修復 migration 往前修 4. View/SP 用 `R__*.sql` 管理 5. 必要的系統參數/字典資料用 seed migrations 管理 --- ## 9. 快速檢查清單 ### 9.1 基本必備 * [ ] **依賴已加入**:`org.flywaydb:flyway-core` * [ ] **JDBC Driver 已加入**:PostgreSQL / SQL Server / Oracle 對應 driver(專案能正常連線 DB) * [ ] **Datasource 設定正確**:`spring.datasource.url / username / password`(與環境一致) * [ ] **migrations 路徑正確**:預設 `classpath:db/migration`(或 `spring.flyway.locations` 已正確指定) * [ ] **檔名規則正確**:`V<版本>__<描述>.sql`(注意雙底線 `__`,版本號建議用遞增整數或語意化序列) * [ ] **第一次啟動**:DB 會建立 `flyway_schema_history`(代表 Flyway 有在跑) * [ ] **之後啟動**:只會執行「新增且尚未執行」的版本(不會每次從 V1 重跑) ### 9.2 團隊流程必備(避免環境漂移) * [ ] **已跑過的 migration 檔不要修改**(避免 checksum 不一致導致啟動失敗) * [ ] **所有 DDL 變更都用新增 migration**(不要手動改正式 DB;dev 也盡量不要手改 DDL) * [ ] **PR/Code Review 檢查**:migration 是否可重播、是否破壞相容(例如欄位改型別、drop 欄位) * [ ] **部署順序固定**:先跑 Flyway(migrate)→ 再部署應用程式(避免程式先上但 DB 還沒更新) ### 9.3 常見設定檢查(視情況) * [ ] **既有 DB 接管**:若 schema 非空且之前不是 Flyway 管的,考慮:`spring.flyway.baseline-on-migrate=true` * [ ] **分階段上線**:需要控制只跑到某版時,設定:`spring.flyway.target=<version>` * [ ] **Repeatable**:View / SP / Function 等需要可重複更新者,用 `R__*.sql` * [ ] **多 schema**:需要時設定 `spring.flyway.schemas=...`(並確認權限足夠) * [ ] **禁止危險操作**:正式環境避免開 `clean`(若你有用到 Flyway 的 clean 機制) ### 9.4 與 JPA/Hibernate 搭配(建議) * [ ] **正式環境**:`spring.jpa.hibernate.ddl-auto` 建議 `validate` 或 `none`(避免 Hibernate 直接改 schema) * [ ] **開發環境**:仍建議 Flyway 管 schema;`ddl-auto` 只用 `validate` 輔助檢查(避免 update 自動改表造成不可控差異) * [ ] **啟動順序**:確保 Flyway 在 JPA 初始化前完成 migrate(Spring Boot 預設通常會幫你處理) --- 如果你願意貼你的 `application.yml`(datasource + flyway + jpa),我可以幫你對照這份清單逐項檢查哪裡少了/可能踩雷。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up