728x90
반응형

DB 형상관리 - liquibase

Liquibase

  • Liquibase 는 개발부터 product 생산까지 데이터베이스 변경 사항을 보다 빠르고 안전하게 수정하고 릴리스할 수 있는 데이터베이스 스키마 변경 관리 솔루션.

Liquibase가 제공하는 기능

  • Changeset: database 변경 사항을 정의
  • Changelog: 데이터베이스 변경을 파일로 기록
  • Update: 다양한 실행 커맨드를 통해 Liquibase 조작

Liquibase 파일 형식

XML

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
    xmlns:pro="http://www.liquibase.org/xml/ns/pro"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
        http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
    <changeSet id="1" author="Liquibase">
    <createTable tableName="test_table">
           <column name="test_id" type="int">
                 <constraints primaryKey="true"/>
           </column>
           <column name="test_column" type="varchar"/>
    </createTable>
    </changeSet>
</databaseChangeLog>

SQL

--liquibase formatted sql

--changeset liquibase:1
CREATE TABLE test_table (test_id INT, test_column VARCHAR, PRIMARY KEY (test_id))

 

YML

databaseChangeLog:
   - changeSet:
       id: 1
       author: Liquibase
       changes:
       - createTable:
           columns:
           - column:
               name: test_column
               type: INT
               constraints:  
                   primaryKey:  true  
                   nullable:  false  
                   tableName: test_table

JSON

{ 
  "databaseChangeLog": [
  {
	"changeSet": {
	  "id": "1",
      "author": "Liquibase",
	  "changes": [
	    {
		  "createTable": {
		    "columns": [
			{
			  "column": 
		      {
				"name": "test_column",
				"type": "INT",
				"constraints": 
			  {
				"primaryKey": true,
				"nullable": false
				}
				}
			  }]
			,
			"tableName": "test_table"
		  }
		}]
	  }
	}]
  }

Flyway 와 Liquibase 의 차이점 - 1

  • Flyway의 경우 SQL 파일만 지원.
  • Liquibase의 경우 다양한 파일 형식 지원 (그러나, 공식문서에서는 XML 파일 형식을 가장 많이 사용하는 듯)

Liquibase with Maven

pom.xml

<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
</dependency>

<plugin>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-maven-plugin</artifactId>
    <version>4.28.0</version>
    <configuration>
        <!--set values for Liquibase properties and settings
        for example, the location of a properties file to use-->
        <propertyFile>liquibase.properties</propertyFile>
     </configuration>
     <dependencies>
         <!--set up any dependencies for Liquibase to function in your
         environment for example, a database-specific plugin-->
         <dependency>
             <groupId>org.liquibase.ext</groupId>
             <artifactId>liquibase-<dbname></artifactId>
             <version>4.28.0</version>
        </dependency>
     </dependencies>
</plugin>

application.properties

# Default Path : classpath:/db/changelog/db.changelog-master.yaml
spring.liquibase.change-log=classpath:db/changelog/changelog-master.xml

liquibase.properteis

# 테스트 결과 따로 설정하지 않아도 기존의 DB Connection을 따라서 적용됨.
contexts: ${liquibase.contexts}
changeLogFile: com/company/client/project/changelog.xml
driver: ${dataSource.project.driverClass}
url: ${dataSource.project.jdbcURL}   
verbose: true
dropFirst: false

데이터 베이스에 변경 사항을 적용하기 전 SQL 검사

mvn liquibase:updateSQL

데이터베이스에 변경사항 배포

mvn liquibase:update

Liquibase ChangeSet Option

속성
설명
예제 값
id
각 changeSet의 고유 식별자
1, 2, myChangeSetId
author
변경 사항을 작성한 사람의 이름
your_username, admin
runAlways
true로 설정하면 변경 사항이 매번 실행됨
true, false
runOnChange
true로 설정하면 변경 사항의 내용이 변경될 때마다 실행됨
true, false
failOnError
true로 설정하면 변경 사항 실행 중 오류 발생 시 실행을 중단함
true, false
context
변경 사항을 실행할 특정 컨텍스트 지정
dev, test, prod
dbms
변경 사항을 실행할 특정 데이터베이스 관리 시스템 지정
mysql, postgresql
labels
라벨을 지정하여 특정 라벨이 지정된 경우에만 실행
label1, label2
logicalFilePath
논리적 파일 경로를 지정하여 동일한 변경 사항을 다른 위치에서 실행할 수 있도록 함
src/main/resources/db/changelog/db.changelog-master.xml
runInTransaction
true로 설정하면 변경 사항이 트랜잭션 내에서 실행됨
true, false
objectQuotingStrategy
객체 이름을 따옴표로 묶는 방법을 지정
LEGACY, QUOTE_ALL_OBJECTS, QUOTE_ONLY_RESERVED_WORDS
comment
변경 사항에 대한 설명을 추가
Create users table
onValidationFail
유효성 검사 실패 시 수행할 작업 지정 (HALT, MARK_RAN)
HALT, MARK_RAN

Liquibase vs Flyway

요약

  • 해당 관리도구들을 통해 데이터베이스 관리 및 배포를 적극 사용할 경우 Liquibase 압승

테스트

[ 테스트 - 1 ] 정상 프로세스

Tree

.
├── java
│   └── com
│       └── douzone
│           └── platform
├── resources
│   ├── db
│   │   └── changelog
│   │       └── changelog-master.xml

changelog-master.xml

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xmlns:pro="http://www.liquibase.org/xml/ns/pro"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
        http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
    <changeSet id="1" author="Liquibase">
        <createTable tableName="test_table">
            <column name="test_id" type="int">
                <constraints primaryKey="true"/>
            </column>
            <column name="test_column" type="varchar"/>
        </createTable>
    </changeSet>
</databaseChangeLog>
  • Liquibase의 경우 Flyway와 동일할게 변경을 추적할 수 있는 테이블이 자동으로 생성됨.
  • 그러나, 2개의 테이블이 생성됨 databasechangelog, databasechangeloglock
  • databasechangelog
  • databasechangeloglock

[ 테스트 - 2] ChangeSet 추가 (테이블 변경사항 추가)

changelog-master.xml

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xmlns:pro="http://www.liquibase.org/xml/ns/pro"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
        http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
    <changeSet id="1" author="Liquibase">
        <createTable tableName="test_table">
            <column name="test_id" type="int">
                <constraints primaryKey="true"/>
            </column>
            <column name="test_column" type="varchar"/>
        </createTable>
    </changeSet>

    <!--  새로운 Changeset 추가  -->
    <changeSet id="2" author="Liquibase">
        <addColumn tableName="test_table">
            <column name="new_column" type="varchar(255)"/>
        </addColumn>
    </changeSet>
</databaseChangeLog>
  • 성공적인 실행
  • databasechangelog 새로운 row가 추가되면서 기록됨.

[ 테스트 - 3 ] Changeset에 실패하게 될 명령어를 추가하게 된다면?

changelog-master.xml

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xmlns:pro="http://www.liquibase.org/xml/ns/pro"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
        http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
    <changeSet id="1" author="Liquibase">
        <createTable tableName="test_table">
            <column name="test_id" type="int">
                <constraints primaryKey="true"/>
            </column>
            <column name="test_column" type="varchar"/>
        </createTable>
    </changeSet>

    <!--  새로운 Changeset 추가  -->
    <changeSet id="2" author="Liquibase">
        <addColumn tableName="test_table">
            <column name="new_column" type="varchar(255)"/>
        </addColumn>
    </changeSet>
    
    <!--  실패할 명령어  -->
    <changeSet id="3" author="Liquibase">
        <addColumn tableName="test_table">
            <column name="new_column" type="varchar(255)"/>
        </addColumn>
    </changeSet>
</databaseChangeLog>
  • SQL 명령어 실패하면서 서버 실행 실패.
  • databasechangelog 에 기록 저장 X

[ 테스트 - 4 ] SQL 문으로 실행

application.properteis

spring.liquibase.change-log=classpath:db/changelog/changelog-master.sql

changelog-master.sql

--liquibase formatted sql

--changeset mgkang1:1
CREATE TABLE test_sql_table (test_id INT, test_column VARCHAR, PRIMARY KEY (test_id))
  • 성공적으로 반영됨.

[ 테스트 - 5 ] SQL 문으로 실행 AND 주석 처리

changelog-master.sql

--liquibase formatted sql

--changeset mgkang1:1
CREATE TABLE test_sql_table (test_id INT, test_column VARCHAR, PRIMARY KEY (test_id))

--changeset mgakng1:2
-- ALTER TABLE test_sql_table ADD COLUMN new_column VARCHAR(255);
  • 성공
728x90
반응형
MyeongDev