1. 程式人生 > >如果你是一個縣長,吃著火鍋唱著歌,突然就被麻匪給劫了。

如果你是一個縣長,吃著火鍋唱著歌,突然就被麻匪給劫了。

Flyway簡介

總結:Flyway可以很方便的幫我們完成資料庫部署和增量升級,很有用,但是版本回滾操作並不給力~~~

1、簡介

1.1、Flyway是什麼

Flyway是一款資料庫遷移(migration)工具。簡單點說,就是在你部署應用的時候,幫你執行資料庫指令碼的工具。Flyway支援SQL和Java兩種型別的指令碼,你可以將指令碼打包到應用程式中,在應用程式啟動時,由Flyway來管理這些指令碼的執行,這些指令碼被Flyway稱之為migration。

就目前而言,我們部署應用的流程大概是這樣的:

  • 開發人員將應用程式打包、按順序彙總並整理資料庫升級指令碼
  • DBA拿到資料庫升級指令碼檢查、備份、執行,以完成資料庫升級
  • 應部署人員拿到應用部署包,備份、替換,以完成應用程序升級

引入Flyway之後的應用部署流程大概是這樣的:

  • 開發人員將應用程式打包
  • 應部署人員拿到應用部署包,備份、替換,以完成應用程序升(Flyway將自動執行升級/備份指令碼)

1.1、Flyway如何工作

最簡單的理解方式是:簡單我們在一個空資料庫上部署集成了Flyway的應用:

這裡寫圖片描述

Flyway將在這個空資料中建立一張表,用於記錄migration的執行情況,表名稱預設為:flyway_schema_histor,老版本的表名稱:schema_version

這裡寫圖片描述

緊接著,Flyway根據表中的記錄決定是否執行應用程式包中提供的migration

這裡寫圖片描述

最後將執行結果寫入flyway_schema_histor並校驗執行結果

這裡寫圖片描述

下次版本迭代時,提供新的migration,會根據flyway_schema_histor的記錄執行新migration

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

2、核心概念

2.1、Migration

Flyway將每一個數據庫指令碼稱之為:migrations,flyway支援三種類型的migration:

  • Versioned migrations:最常用的migration,可以簡單的理解為資料庫升級指令碼
  • Undo migrations:資料庫版本回退指令碼,需要Pro版本,忽略,而且使用過程存在較大風險,undo操作目前只能通過plugin或者command-line來執行
  • Repeatable migrations:可重複執行的migration,例如create or replace指令碼,當指令碼checksums改變時會重新執行

每個migration支援兩種編寫方式:

  • Java:通過實現 org.flywaydb.core.api.migration.jdbc.JdbcMigratio 介面來建立一個Java migration,也就是通過JDBC來執行SQL,對於類是CLOB或者BOLB這種不方便在SQL中實現的指令碼比較有用,例如:
package db.migration;

import org.flywaydb.core.api.migration.jdbc.JdbcMigration;
import java.sql.Connection;
import java.sql.PreparedStatement;

/**
 * Example of a Java-based migration.
 */
public class V1_2__Another_user implements JdbcMigration {
    public void migrate(Connection connection) throws Exception {
        PreparedStatement statement = connection.prepareStatement("INSERT INTO test_user (name) VALUES ('Obelix')");
        try {
            statement.execute();
        } finally {
            statement.close();
        }
    }
}
  • SQL:簡單的SQL指令碼檔案,例如:
/* Single line comment */
CREATE TABLE test_user (
  name VARCHAR(25) NOT NULL,
  PRIMARY KEY(name)
);

/*
Multi-line
comment
*/
-- Placeholder
INSERT INTO ${tableName} (name) VALUES ('Mr. T');

所有的migration都需要遵守命名規範:

這裡寫圖片描述

確保版本號唯一,flyway按照版本號順序執行。repeatable沒有版本號,因為repeatable migrations會在內容改變時重複執行

預設情況下,flyway會將單個migration放在一個事物裡執行,也可以通過配置將所有migration放在同一個事物裡執行,感覺用處不大,這裡就不介紹了~

2.2、Callbacks

Flyway在執行migrations時提供了一些列的hook,使你可以在執行過程中加入額外的操作:

這裡寫圖片描述

這些hook均執行SQL和Java型別的migrations,只需要將migration的名稱以hook名稱開頭即可,例如:beforeMigrate.sqlbeforeEachMigrate.sqlbeforeRepair__vacuum.sql ,Java型別的hook需要實現介面:org.flywaydb.core.api.callback.Callback

2.3、Error Handlers

2.4、Dry Runs

3、使用事例

3.1、整合Spring Boot

  • build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '2.0.2.RELEASE'
}

group 'com.chenlei'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.2.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-jdbc', version: '2.0.2.RELEASE'

    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.46'

    compile group: 'org.flywaydb', name: 'flyway-core', version: '5.1.1'

    testCompile group: 'junit', name: 'junit', version: '4.12'
}
  • application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://192.168.119.123:3306/flyway?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: flyway
    password: Flyway@1234
    driver-class-name: com.mysql.jdbc.Driver
  flyway:
    locations: classpath:com/chenlei/flyway/db/mysql

這裡寫圖片描述

3.2、Gradle外掛

  • build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '2.0.2.RELEASE'
    id "org.flywaydb.flyway" version "5.1.1"
}

flyway {
    url = 'jdbc:mysql://192.168.119.123:3306/flyway?useUnicode=true&characterEncoding=utf-8&useSSL=false'
    user = 'flyway'
    password = '[email protected]'
    locations = ['classpath:com/chenlei/flyway/db/mysql']
    encoding = 'UTF-8'
}

group 'com.chenlei'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.2.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-jdbc', version: '2.0.2.RELEASE'

    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.46'

    compile group: 'org.flywaydb', name: 'flyway-core', version: '5.1.1'

    testCompile group: 'junit', name: 'junit', version: '4.12'
}

注意:

  • Clean會將資料庫schema下的所有內容清空,謹慎執行
  • Baseline的版本號和migration衝突時,migration不會執行
  • Repeatable僅在check sum傳送改變時會再次執行,Java migration需要實現 org.flywaydb.core.api.migration.MigrationInfoProvider 介面
  • Gradle查詢無法執行實現 org.flywaydb.core.api.migration.spring.SpringJdbcMigration 介面的migrations,只能是實現 org.flywaydb.core.api.migration.jdbc.JdbcMigration 的migrations
  • Undo需要Pro版本

這裡寫圖片描述

Maven外掛與此類似~

4、參考資料