Pendahuluan
Liquibase adalah sistem kontrol versi database, ini terutama menyangkut struktur dan, pada tingkat lebih rendah, isi dari database. Selain itu, deskripsi database, di satu sisi, agak abstrak dan memungkinkan penggunaan berbagai DBMS di tingkat yang lebih rendah, dan di sisi lain, Anda selalu dapat beralih ke dialek SQL dari DBMS tertentu, yang cukup fleksibel. Liquibase adalah proyek open source yang mapan dan secara aktif digunakan di luar lingkungan asli Jawa dan tidak memerlukan pengetahuan mendalam tentang Java untuk bekerja. Format XML secara historis telah digunakan untuk menggambarkan struktur dasar dan perubahan basis, tetapi sekarang YAML dan JSON didukung secara paralel.
Dalam artikel ini, kami akan merangkum secara singkat pengalaman generasi sebelumnya dan fokus bekerja dengan Liquibase menggunakan Maven. Kami akan menggunakan Ubuntu sebagai sistem operasi pengujian.
Artikel lain tentang Liquibase
Pengaturan lingkungan
Ada beberapa cara untuk memulai Liquibase, namun, paling mudah menggunakan Maven atau Gradle.
sudo apt install maven mvn -version
Di sini pom.xml bertindak sebagai Makefile - sudah berisi semua dependensi, pengaturan, dan profil yang diperlukan.
pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test.db</groupId> <artifactId>db</artifactId> <version>1.0.0</version> <name>db</name> <description>Test Database</description> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <slf4j.version>1.7.24</slf4j.version> <logback.version>1.2.3</logback.version> <liquibase.version>3.6.2</liquibase.version> <postgresql.version>42.2.5</postgresql.version> <snakeyaml.version>1.23</snakeyaml.version> </properties> <dependencies> <!--Logging--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!--JDBC drivers--> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>${postgresql.version}</version> </dependency> <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>${liquibase.version}</version> </dependency> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>${snakeyaml.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>${liquibase.version}</version> <configuration> <propertyFile>${profile.propertyFile}</propertyFile> <changeLogFile>${profile.changeLogFile}</changeLogFile> <dataDir>${profile.dataDir}</dataDir> <!-- log --> <verbose>${profile.verbose}</verbose> <logging>${profile.logging}</logging> <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase> </configuration> </plugin> </plugins> </build> <profiles> <!-- Development settings, -Denv=dev --> <profile> <id>dev</id> <activation> <property> <name>env</name> <value>dev</value> </property> </activation> <properties> <profile.propertyFile>dev/liquibase.properties</profile.propertyFile> <profile.changeLogFile>dev/master.xml</profile.changeLogFile> <profile.dataDir>dev/data</profile.dataDir> <profile.verbose>true</profile.verbose> <profile.logging>debug</profile.logging> </properties> </profile> <!-- Production settings, -Denv=prod --> <profile> <id>prod</id> <activation> <property> <name>env</name> <value>prod</value> </property> </activation> <properties> <profile.propertyFile>prod/liquibase.properties</profile.propertyFile> <profile.changeLogFile>prod/master.xml</profile.changeLogFile> <profile.dataDir>prod/data</profile.dataDir> <profile.verbose>false</profile.verbose> <profile.logging>info</profile.logging> </properties> </profile> </profiles> </project>
Kami meluncurkan pembaruan
Setelah kita melakukan pom.xml, kita dapat mulai memperbarui database - perintah liquibase: update.
Untuk ini kita perlu:
- File liquibase.properties dengan pengaturan untuk menghubungkan ke database (nama pengguna / kata sandi dan mungkin parameter lainnya)
- file xml dengan perubahan basis
- sh skrip startup pembaruan database
File pengaturan koneksi basis data
properti liquibase
username=test password=test referenceUsername=test # #url=jdbc:postgresql://dev/test #referenceUrl=jdbc:postgresql://dev/test_reference
Basis perubahan file
Konsep utama liquibase adalah apa yang disebut perubahan dasar (perubahan). Mereka dapat mencakup perubahan struktural dan perubahan data. Liquibase menggunakan tabel databasechangelog dan databasechangeloglock untuk memantau perubahan yang diterapkan.
<?xml version="1.1" encoding="UTF-8" standalone="no"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> <changeSet context="legacy" author="author (generated)" id="1"> <createTable tableName="test"> <column autoIncrement="true" name="id" type="SERIAL"> <constraints nullable="false"/> </column> <column name="user_name" type="VARCHAR(255)"/> <column name="preferences" type="TEXT"/> </createTable> </changeSet> </databaseChangeLog>
Skrip startup pembaruan basis data
Di sini liquibase: pembaruan dijalankan untuk profil dev dan basis dari liquibase.url, yang ditentukan dalam format JDBC standar. Setelah pembaruan, tabel yang ditunjukkan dalam changeSet dan dua tabel layanan databasechangelog dan databasechangeloglock muncul di database .
#!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"
Pembuatan SQL tanpa memperbarui database
Terkadang, sebelum memulai perubahan, Anda perlu melihat konten dari permintaan yang dihasilkan. Perintah liquibase: updateSQL dan liquibase: rollbackSQL dimaksudkan untuk tujuan ini.
#!/usr/bin/env bash mvn liquibase:updateSQL\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified" > /tmp/script.sql
Lebih lanjut tentang changeSet
Perubahan bisa dalam format yang berbeda, termasuk sql biasa atau dalam file terpisah.
Setiap perubahan dapat menyertakan bagian rollback yang memungkinkan Anda untuk memutar kembali perubahan dengan perintah liquibase: rollback . Selain itu, Anda dapat menggunakan tagDatabase untuk menandai perubahan, misalnya, untuk memutar kembali ke sana dengan lebih mudah.
<changeSet context="legacy" author="author (generated)" id="1"> <createTable tableName="test"> <column autoIncrement="true" name="id" type="SERIAL"> <constraints primaryKey="true" primaryKeyName="test_pkey"/> </column> <column name="c1" type="VARCHAR(255)"/> <column name="c2" type="INTEGER"/> <column name="c3" type="SMALLINT"/> <column name="c4" type="VARCHAR(255)"/> <column name="c5" type="TEXT"/> <column name="c6" type="VARCHAR(255)"/> </createTable> </changeSet>
SQL tertanam
<changeSet context="legacy" author="author" id="1-domain-some-domain"> <sql> CREATE DOMAIN public.some_domain AS bigint; ALTER DOMAIN public.some_domain OWNER TO test; </sql> <rollback> DROP DOMAIN public.some_domain; </rollback> </changeSet>
File SQL
<changeSet context="legacy" author="author" id="1-user"> <sqlFile dbms="postgresql" path="sql/some.sql" relativeToChangelogFile="true" /> <rollback> delete from "some"; </rollback> </changeSet>
Tag
<changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet>
Luncurkan konteks
Untuk manajemen yang lebih nyaman dari berbagai konfigurasi, misalnya, pengembangan / produksi, konteks dapat digunakan. Konteks ditentukan dalam atribut changeSet dari konteks dan kemudian diluncurkan oleh Maven dengan parameter -Dcontexts.
Ubah dengan konteks
<changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet>
Memicu Perubahan Konteks
#!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy
Kembalikan perubahan
Operasi ini kebalikan dari memperbarui, dalam banyak kasus itu didukung secara otomatis. Bagi yang lain, tugas dimungkinkan melalui bagian rollback. Ini diluncurkan oleh perintah liquibase: rollback.
Ubah dengan rollback
<changeSet context="legacy" author="author" id="1-domain-some-domain"> <sql> CREATE DOMAIN public.some_domain AS bigint; ALTER DOMAIN public.some_domain OWNER TO test; </sql> <rollback> DROP DOMAIN public.some_domain; </rollback> </changeSet>
Luncurkan kembalikan
#!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy
Perbandingan
Dalam pengembangan, lebih mudah digunakan untuk membandingkan dua database yang ada untuk perubahan yang dilakukan. Dalam pengaturan (atau parameter peluncuran), Anda perlu menambahkan tautan ke database referensi dan data untuk mengaksesnya.
properti liquibase
referenceUsername=test referenceUrl=jdbc:postgresql://dev/test_reference
Perbandingan sirkuit
Membandingkan skema url dan referenceUrl.
#!/usr/bin/env bash mvn liquibase:diff\ -Denv=dev\ -Dliquibase.referenceUrl="jdbc:postgresql://dev/test?prepareThreshold=0"\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.diffChangeLogFile=dev/diff.xml
Skema Penghematan
Dapat juga berguna untuk menyimpan skema basis data saat ini, dengan atau tanpa data. Harus diingat bahwa Liquibase menyimpan skema yang tidak sepenuhnya sesuai dengan yang asli, misalnya, domain yang digunakan atau warisan harus ditambahkan secara terpisah (lihat Pembatasan).
Menyimpan skema tanpa memperhitungkan data
Menyimpan skema dari database yang ada.
#!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml
Menyimpan skema dengan data
Menyimpan skema database yang ada dengan data.
#!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml
Keterbatasan dan masalah
Bekerja dengan data biner dalam database
Ada masalah tertentu dengan mengunggah, membandingkan dan menggunakan data biner, khususnya, masalah dengan menghasilkan perubahan.
Warisan dan kolom umum
Kode sumber
Solusi alternatif
Jalur terbang
Seiring dengan Liquibase populer di komunitas Jawa - http://flywaydb.org/documentation
Sqqitch
Perl setara - http://sqitch.org
Fluentmigrator
Analog untuk .Net - https://github.com/schambers/fluentmigrator
Dbgeni
Analogue for Ruby - http://dbgeni.appsintheopen.com/manual.html
Aplikasi
Struktur proyek
pom.xml - maven makefile dev liquibase.properties - login/password etc master.xml - changesets
Bagaimana cara menambahkan liquibase ke proyek yang ada
Bagaimana perubahan basis bekerja
Lebih lanjut tentang pembaruan
Lebih lanjut tentang Ubah Generasi
Lebih lanjut tentang SQL kustom
Memproses tipe data basis data khusus
<createTable tableName="t_name"> ... <column name="doubleArray" type="DOUBLE_ARRAY"/> ... </createTable> <modifySql dbms="postgresql"> <replace replace="DOUBLE_ARRAY" with="double precision[][]"/> </modifySql>
Lainnya