在項目迭代開發中,不免會有更新數據庫 Schema 的狀況,好比添加新表、在表中增長字段或者刪除字段等,那麼當我對數據庫進行一系列操做後,如何快速地在其餘同事的電腦上同步?如何在測試/生產服務器上快速同步?mysql
每次發版的時候,因爲你們均可能有 sql 更改狀況,這樣就會有如下痛點:git
以上問題以及痛點能夠經過 Flyway 工具來解決,Flyway 能夠實現自動化的數據庫版本管理,而且可以記錄數據庫版本更新記錄。github
Flyway 是獨立於數據庫的應用、管理並跟蹤數據庫變動的數據庫版本管理工具。用通俗的話講,Flyway 能夠像 Git 管理不一樣人的代碼那樣,管理不一樣人的 sql 腳本,從而作到數據庫同步,更多的信息能夠在 Flyway 的官網上進行閱讀學習。spring
另外 Flyway 支持不少關係數據庫,具體以下所示:sql
下面咱們在 Spring Boot 中集成 Flyway 來實現數據庫版本控制。數據庫
首先建立一個 SpringBoot 項目,而後在 pom.xml
加入以下依賴集成 Flyway:api
<dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>5.2.4</version> </dependency>
而後在 application.yml
中寫入 mysql 的配置及 Flyway 的相關配置(Flyway locations 默認讀取當前項目下的 resources/db/migration
目錄)數組
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123 spring.flyway.locations=classpath:/db/migration/
接下來,在 resources/db/migration
目錄下建立須要執行的 SQL 腳本便可。服務器
其中,SQL 腳本命名規範以下:app
.
和整數組成__
組成.sql
組成,若是是基於 Java 類則默認不須要後綴那麼,咱們按照命名規範在 resources/db/migration
目錄下,建立 V1.0__init_db.sql
SQL 遷移腳本,具體內容以下:
DROP TABLE IF EXISTS `user` ; CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵', `name` varchar(20) NOT NULL COMMENT '姓名', `age` int(11) DEFAULT NULL COMMENT '年齡', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `user` (`id`, `name`, `age`) VALUES ('1', 'wupx', '18');
最後啓動項目,執行日誌以下所示:
2020-05-07 12:41:29.126 INFO 13732 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.4 by Boxfuse 2020-05-07 12:41:29.236 INFO 13732 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:mysql://localhost:3306/test (MySQL 5.5) 2020-05-07 12:41:29.287 INFO 13732 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.009s) 2020-05-07 12:41:29.330 INFO 13732 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table: `test`.`flyway_schema_history` 2020-05-07 12:41:29.479 INFO 13732 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `test`: << Empty Schema >> 2020-05-07 12:41:29.480 INFO 13732 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `test` to version 1.0 - init db 2020-05-07 12:41:29.481 WARN 13732 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Unknown table 'user' (SQL State: 42S02 - Error Code: 1051) 2020-05-07 12:41:29.631 INFO 13732 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `test` (execution time 00:00.301s)
從啓動日誌中能夠看出,Flyway 監測到須要運行版本腳原本初始化數據庫,所以執行了 V1.0__init_db.sql
腳本,從而建立了 user
表,另外還自動建立了 flyway_schema_history
表,用於記錄全部版本演化和狀態,其表結構以下(以 MySQL 爲例):
Field | Type | Null | Key | Default |
---|---|---|---|---|
version_rank | int(11) | NO | MUL | NULL |
installed_rank | int(11) | NO | MUL | NULL |
version | varchar(50) | NO | PRI | NULL |
description | varchar(200) | NO | NULL | |
type | varchar(20) | NO | NULL | |
script | varchar(1000) | NO | NULL | |
checksum | int(11) | YES | NULL | |
installed_by | varchar(100) | NO | NULL | |
installed_on | timestamp | NO | CURRENT_TIMESTAMP | |
execution_time | int(11) | NO | NULL | |
success | tinyint(1) | NO | MUL | NULL |
查詢 flyway_schema_history
表,發現增長了一條版本號爲 1.0
的,使用 V1.0__init_db.sql
遷移腳本的記錄。
mysql> SELECT * FROM flyway_schema_history; +----------------+---------+-------------+------+-------------------+------------+--------------+---------------------+----------------+---------+ | installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success | +----------------+---------+-------------+------+-------------------+------------+--------------+---------------------+----------------+---------+ | 1 | 1.0 | init db | SQL | V1.0__init_db.sql | 1317299633 | root | 2020-05-07 12:41:29 | 97 | 1 | +----------------+---------+-------------+------+-------------------+------------+--------------+---------------------+----------------+---------+
再去查詢 user
表,發現 sql 腳本中的數據也插入成功了。
mysql> SELECT * FROM user; +----+------+-----+ | id | name | age | +----+------+-----+ | 1 | wupx | 18 | +----+------+-----+
接下來再次運行項目,結果以下:
2020-05-07 15:34:49.843 INFO 41880 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.4 by Boxfuse 2020-05-07 15:34:49.981 INFO 41880 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:mysql://localhost:3306/test (MySQL 5.5) 2020-05-07 15:34:50.036 INFO 41880 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.013s) 2020-05-07 15:34:50.043 INFO 41880 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `test`: 1.0 2020-05-07 15:34:50.043 INFO 41880 --- [ main] o.f.core.internal.command.DbMigrate : Schema `test` is up to date. No migration necessary.
從日誌中能夠看出,Flyway 發現一個遷移腳本,也就是 V1.0__init_db.sql
,通過判斷已經到達最新版本 1.0,無需執行遷移。
接下來,咱們在 V1.0__init_db.sql
遷移腳本中添加一條 INSERT 操做:INSERT INTO
user (
id,
name,
age) VALUES ('2', 'huxy', '18');
,再次啓動項目,會報以下錯誤:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Validate failed: Migration checksum mismatch for migration version 1.0 -> Applied to database : 1317299633 -> Resolved locally : -1582367361
這個錯誤的緣由就是 Flyway 會給腳本計算一個 checksum 保存在數據庫中,用於在以後運行過程當中對比 sql 文件是否有變化,若是發生了變化,則會報錯,也就防止了誤修改腳本致使發生問題。
Flyway 能夠有效改善數據庫版本管理方式,而且是一款 Java 開源的數據庫遷移管理工具,具備輕便小巧的特色,能夠無門檻快速集成到項目中,若是項目中還未使用,不防嘗試一下,想了解更多的能夠去官網查看文檔學習。
本文的完整代碼在 https://github.com/wupeixuan/... 的 database-version-control
目錄下。
最好的關係就是互相成就,你們的在看、轉發、留言三連就是我創做的最大動力。
參考