+6

Migration data với Flyway sử dụng Maven cho multiple database servers

Bài viết hôm này mình sẽ giới thiệu về flyway, một Java library sử dụng để migration data, khi cấu trúc hoặc data thay đổi trong quá trình phát triển dự án mà cần nâng cấp database version.

Google với từ khóa Flywaydb tutorial hoặc flywaydb migration có lẽ bạn sẽ tìm ra vô số các bài viết từ nhiều nguồn khác nhau. Nhưng bài viết này, mình vẫn mong muốn chia sẻ một bài viết thuần việt, sau những gì mình đã tìm hiểu được và áp dụng.

Bài viết có sử dụng một số hình ảnh tham khảo trên internet.

Index

  • Flyway là gì
  • Flyway hoạt động như thế nào
  • Các loại migrations
  • Quy tắc đặt tên version
  • Sample - Tích hợp flyway maven plugin
  • Cấu hình maven profile với flyway
    • Maven profile là gì
    • Config maven profile
    • Migrating với các servers
  • Tổng kết

Flyway là gì

Flyway là một java open source library hỗ trợ migrate data cho các ứng dụng, một khi chúng ta cần:

  • Nâng cấp database do thay đổi cấu trúc hoặc dữ liệu.
  • Quản lý lịch sử thay đổi version một cách chặt chẽ.
  • Thực thi migrating một cách tự động.
  • Đồng bộ data structure giữa các server development.

Nó hỗ trợ cài đặt , cấu hình cực kỳ đơn giản. Bạn chỉ cần download flyway từ homepage, giải nén, và chạy các flyway executable với các tham số tương ứng đến database, sql script ..vv . Hoặc bạn cũng có thể tích hợp nó trong chính ứng dụng như một tính năng upgrade database khi cần thiết.

Đoạn dưới là ví dụ mô tả khi thực hiện migrate data bằng Command lineJava API :

flyway migrate -url=... -user=... -password=...
Flyway flyway = new Flyway();
flyway.setDataSource(url, user, password);
flyway.migrate();

Hiện tại, flyway cũng hỗ trợ các build tools, dependency manager gồm : Maven, Gradle , Ant và SBT build tool for Scala. Ngoài ra còn hỗ trợ tích hợp các plugins để dễ dàng config và sử dụng với các ứng dụng có framework đặc thù.

Hỗ trợ hầu hết các relational database

Flyway hoạt động như thế nào

Flyway tạo ra một table có tên SCHEMA_VERSION dùng để quản lý lịch sử phiên bản cũng như trạng thái của database.

Các file chạy migrate có thể là file Sql script hoặc Java API là những class VerXXX_Jdbc*** được extends từ flyway core. Các file này đều được đặt tên theo một quy tắc nhất định để xác định version number.

Tại mỗi thời điểm chạy migration. flyway sẽ kiểm tra SCHEMA_VERSION và quét cần migrate để kiểm tra việc migrating tới một version mới hay không. Nếu version đó nhỏ hơn hoặc bằng version hiện tại quá trình này sẽ được bỏ qua.

Để hình dung quá trình thay đổi database , bạn hãy nhìn hình bên dưới :

Dữ liệu được log trong SCHEMA_VERSION :

installed_rank version description type script checksum installed_by installed_on execution_time success
1 1 Initial Setup SQL V1__Initial_Setup.sql 1996767037 axel 2016-02-04 22:23:00.0 546 true
2 2 First Changes SQL V2__First_Changes.sql 1279644856 axel 2016-02-06 09:18:00.0 127 true

Các loại migrations

Flyway support 2 loại migrations là Versioned migrationsRepeatable migrations.

Versioned migrations : là các versions đã được định danh và có đánh số duy nhất với các version khác, và thường được sử dụng :

  • Creating/altering/dropping tables/indexes/foreign keys/enums/UDTs/...
  • Reference data updates
  • User data corrections

Repeatable migrations : Repeatable thì lại không có version, thay vì đó chúng luôn thực thi sau Versioned migrations mỗi khi có checksum thay đổi từ table SCHEMA_VERSION. Thường được sử dụng :

  • (Re-)creating views/procedures/functions/packages/...
  • Bulk reference data reinserts

Quy tắc đặt tên version

Flyway có thể migrate data bằng file Sql hoặc từ Java class, vì vậy quy tắc đặt tên biến có những sự khác nhau như sau :

Tên file sẽ theo format :

  • prefix: Có thể sử dụng prefix khác, default: V cho versioned migrations, R cho repeatable migrations.
  • version: (chỉ áp dung cho Versioned migrations) có thể thêm dấu . hoặc _ để thêm minor version, ví dụ như : V1_2
  • separator: Có thể sử dụng separator khác, default: __ (2 dấu gạch dưới __)
  • description: Dấu gạch dưới hoặc khoảng trắng để phân biệt các từ.
  • suffix: Có thể thiết lập suffix khác, default: .sql

Với Java Migrations thì duy nhất có 2 điểm khác biệt.

  • prefix: luôn luôn là V cho versioned migrations và R cho repeatable migrations.
  • description: luôn luôn là dấu gạch dưới (_) để phân biệt các từ.

Sample - Tích hợp flyway maven plugin

Nội dung phần này :

  • Demo trên ứng dụng Java console
  • Sử dụng flyway maven plugin
  • Sử dụng Sql migrations
  • Database sử dụng là PostgreSQL

Tạo maven project

Tạo java console app sử dụng maven từ command line hoặc IDE.

mvn archetype:generate -B \
        -DarchetypeGroupId=org.apache.maven.archetypes \
        -DarchetypeArtifactId=maven-archetype-quickstart \
        -DarchetypeVersion=1.1 \
        -DgroupId=flyway-maven-sample \
        -DartifactId=flyway-maven-sample \
        -Dversion=1.0-SNAPSHOT \
        -Dpackage=manhnv.flyway.sample

Một project với tên và thư mục flyway-maven-sample được tạo.

Dưới thư mục projet flyway-maven-sample/src/main tạo thư mục resources/db/migration - đây là thư mục sẽ chứa đựng các file sql cho việc migrating.

Cấu trúc thư mục hiện tại sẽ như sau :

flyway-maven-sample
            | src
                | main
                    | java/manhnv/flyway/sample
                    | resources/db/migration
            | pom.xml

Add Jdbc Driver Dependency

Nội dung demo sử dụng PostgreSQL database, vì vậy phần dưới mình sẽ sử dụng postgresql jdbc, bạn có thể sử dụng jdbc tương ứng với loại database của bạn.

Thêm dependency trong file pom.xml

    <dependencies>
        <!--Add postgres jdbc driver-->
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.1-901.jdbc4</version>
        </dependency>
    </dependencies>

Cấu hinh flyway maven plugin

Thêm nội dung sau vào file pom.xml , phần này sẽ thiết lập các parameters cho plugin flyway-maven-plugin cái sẽ sử dụng cho target build của maven.

<project>
....
    <build>
        <plugins>
            <plugin>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-maven-plugin</artifactId>
                <version>4.2.0</version>
                <configuration>
                    <url>jdbc:postgresql://localhost:5432/flyway_demo?currentSchema=public</url>
                    <user>postgres</user>
                    <password>postgres</password>
                </configuration>
            </plugin>
        </plugins>
    </build>
...
</project>
  • url : connection string đến postgres database.
  • user : user name connect đến database.
  • password : password connect đến database.

Ngoài ra, bạn có thể cấu hình một vài thông tin khác nhu :

  • locations : chỉ định folder migration , default : resources/db/migration ( đã tạo ở trên).
  • sqlMigrationPrefix : prefix trong tên file, default là V ( xem lại Quy tắc đặt tên version)
  • sqlMigrationSuffix : suffix trong tên file, default là .sql ( xem lại Quy tắc đặt tên version)

Để biết thêm các thông tin , bạn có thể xem thêm các parameters ở đây https://flywaydb.org/documentation/maven/migrate

Migrating

Tạo file V1__Create_employee_table.sql trong thư mục resources/db/migration :

CREATE TABLE employee (
    employee_id INT NOT NULL,
    employee_name VARCHAR (100) NOT NULL,
    employee_address VARCHAR (256) NOT NULL
);

Cấu trúc hiện tại như sau :


Để chạy migration , thực hiện command sau trong root folder của project :

mvn flyway:migrate

Output :

[INFO] Successfully validated 1 migration (execution time 00:00.005s)
[INFO] Creating Metadata table: "public"."schema_version"
[INFO] Current version of schema "public": << Empty Schema >>
[INFO] Migrating schema "public" to version 1 - Create employee table
[INFO] Successfully applied 1 migration to schema "public" (execution time 00:00.038s).

Tương tự, giờ chúng ta sẽ thử insert một vài records vào employee table.

Tạo file V2__Add_employee_table.sql trong thư mục resources/db/migration :

INSERT INTO employee (employee_id, employee_name, employee_address) VALUES
  (1, 'Nguyen Van A', 'Ha Noi'),
  (2, 'Tran Van B', 'Bac Giang'),
  (3, 'Nguyen Thi C', 'Hai Duong');

Và chạy maven flyway một lần nữa.

mvn flyway:migrate

Nào, giờ thì version up sẽ migrating là 2 như log bên dưới.

[INFO] Database: jdbc:postgresql://localhost:5432/flyway_demo?currentSchema=public (PostgreSQL 9.5)
[INFO] Successfully validated 2 migrations (execution time 00:00.009s)
[INFO] Current version of schema "public": 1
[INFO] Migrating schema "public" to version 2 - Add employee table
[INFO] Successfully applied 1 migration to schema "public" (execution time 00:00.017s).


Việc migrating khá đơn giản phải không.. nếu đặt ra câu hỏi. Vậy tôi muốn triển khai cho nhiều server thì sẽ thế nào khi connection string đến database là khác nhau ?

Chúng ta sẽ cùng tìm hiểu phần dưới Cấu hình maven profile với flyway

Cấu hình maven profile với flyway

Như các bạn đã thấy, việc cấu hình flyway maven chỉ đơn giản việc cấu hình trong pom.xml. Điều đó sẽ là một hạn chế khi việc migrating phải thực hiện cho nhiều server development, với các config khác nhau.

Một giải pháp có thể implement trong trường hợp này đó là Maven Build Profiles http://maven.apache.org/guides/introduction/introduction-to-profiles.html

Maven profile là gì ?

Maven profile cho phép chúng ta switch các file config cho từng môi trường khác nhau, rất thích hợp để tùy biến cho các môi trường khác nhau như test, staging hoặc production.

Chỉ đơn giản với command :

mvn -P <profile-name>

Các profile được khai báo trong file pom.xml và luôn có một profile được active (activeProfiles), ở thời điểm build nó sẽ chọn lựa ra profile-name tương ứng để lấy các parameter settings cho các môi trường khác nhau. Ví dụ : các path folder cấu hình trên các servers, thông tin kết nối database..vv

Config maven profile với flyway.

Giả sử mình đang có 3 server local, teststaging lần lượt với các ip tương ứng là :

  • local : localhost - máy local dev
  • test : 192.168.5.173 - máy cho testing trong giai đoạn phát triển
  • staging : 192.168.5.195 máy cho testing gian đoạn pre-release

Những việc cần làm :

  • Tạo 3 file flyway.properties cho 3 môi trường tương ứng.
  • Tạo 3 profile cho 3 môi trường tương ứng trong pom.xml

src/resources/config/local/flyway.properties :

flyway.url=jdbc:postgresql://localhost:5432/flyway_demo?currentSchema=public
flyway.user=postgres
flyway.password=postgres

src/resources/config/test/flyway.properties :

flyway.url=jdbc:postgresql://192.168.5.173:5432/flyway_demo?currentSchema=public
flyway.user=postgres
flyway.password=postgres

src/resources/config/staging/flyway.properties :

flyway.url=jdbc:postgresql://192.168.5.195:5432/flyway_demo?currentSchema=public
flyway.user=postgres
flyway.password=postgres

Tạo maven profiles

Quay lại với pom.xml, tạm thời comment out thẻ <build> - những gì đã config ở trên

Lần lượt tạo các profile theo format sau, trong đó:

  • id : tên profile lần lượt là local, teststaging.
  • configFile : path tới file flyway.properties tương ứng cho từng môi trường.
<project>
...
    <profiles>
        <profile>
            <id>local</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.flywaydb</groupId>
                        <artifactId>flyway-maven-plugin</artifactId>
                        <version>4.2.0</version>
                        <configuration>
                            <configFile>src/main/resources/config/local/flyway.properties</configFile>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

    <!--Other profiles here-->

    </profiles>
....
<project>

Migrating với các servers

Sau khi cấu hình 3 profiles cho các môi trường, để migation ta dùng command sau :

mvn flyway:migrate -P <profile_name>

Migrating trên local server

Giờ minh sẽ thử chạy lại với local server theo command sau :

mvn flyway:migrate -P local

Output :

[INFO] Database: jdbc:postgresql://localhost:5432/flyway_demo?currentSchema=public (PostgreSQL 9.5)
[INFO] Successfully validated 2 migrations (execution time 00:00.008s)
[INFO] Current version of schema "public": 2
[INFO] Schema "public" is up to date. No migration necessary.

Dễ nhận thấy rằng, database không có gì thay đổi ở phía local, vì nó đã được chạy 2 lần trước đó khi chưa tích hợp maven profile.

Flyway sẽ kiểm tra version hiện tại với table SCHEMA_VERSION và nhận thấy không có gì thay đổi và bỏ qua lần migrating này.

Migrating trên test server

Tương tự như local, phía server teststaging cũng thực hiện với command sau :

mvn flyway:migrate -P test

Output :

[INFO] Database: jdbc:postgresql://192.168.5.173:5432/flyway_demo?currentSchema=public (PostgreSQL 9.5)
[INFO] Creating schema "jibunshoten" ...
[INFO] Creating Metadata table: "jibunshoten"."schema_version"
[INFO] Current version of schema "jibunshoten": null
[INFO] Migrating schema "jibunshoten" to version 1 - Create employee table
[INFO] Migrating schema "jibunshoten" to version 2 - Add employee table
[INFO] Successfully applied 2 migrations to schema "jibunshoten" (execution time 00:00.053s).

Nhìn vào log bạn cũng sẽ thấy, migrating được thực hiện 2 lần, lần lượt với version 1version 2. Và đó là kết quả cho lần đầu migrating trên server mới.

Tổng kết

Vậy là mình đã kết thúc việc giới thiệu cũng như cấu hình library flyway, kết hợp với maven profile để migrating trên nhiều servers.

Full source code cho phần demo này có thể download tại https://github.com/manhnv118/flyway-maven-sample


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.