티스토리 뷰

DB형상관리툴?

테이블 생성, 수정, 삭제 및 기본 데이터 입력 등의 DB를 구성하는 SQL이력을 관리해주는 프로그램입니다.
테이블 단위로 SQL문을 관리해주는 것이 좋습니다.
아래 비교 예제를 통해서 살펴보다 보면 이해가 쉬울 것입니다.

 

들어가기 전에

MariaDB를 이용하여 작업하겠습니다.

docker run --rm --name mariadb -p 3306:3306 -e MARIADB_ROOT_PASSWORD=my-secret-pw -d mariadb:latest

Flyway

DB형상관리를 검색하면 가장 먼저 나올 정도로 많이 사용되는 툴입니다.

  • 특징
    1. sql 파일명 규칙이 있습니다.
  • 장점
    1. 지정한 스키마가 없으면 자동생성합니다.
    2. 다른 폴더에 저장되어 있더라도 버전명 순서에 따라 실행됩니다.
    3. 문서에 적힌 대로 시행착오 없이 잘 실행됩니다.
  • 단점
    1. rollback이 없습니다.(유료 버전에 U라는 파일명을 생성하여 되돌릴 수 있지만 제가 생각하는 rollback은 liquibase의 방식입니다.)

 

1. 설치

아래 링크에서 다운로드 가능합니다.
https://flywaydb.org/download

맥이나 리눅스에서는 brew를 사용하는 것이 가장 간편하게 설치할 수 있습니다.

brew install flyway

 

2. flyway.conf 생성

폴더 구성은 아래와 같습니다.

제가 필요한 설정만 아래에 적용했습니다.
자세한 사항은 링크를 참조하세요.
https://flywaydb.org/documentation/configuration/parameters/

flyway.url=jdbc:mariadb://127.0.0.1:3306 # DB접속 URL
flyway.defaultSchema=flyway    # 기본 스키마 명
flyway.table=migration_history # 히스토리가 저장되는 테이블명
flyway.user=root
flyway.password=my-secret-pw
flyway.connectRetries=60
flyway.locations=filesystem:./migration,filesystem:./seed # SQL폴더 위치

 

3. sql 파일 생성

3-1. migration/V1__Create_language.sql 파일 생성

*주의사항

  • 반드시 대문자 V로 시작합니다.
  • V1 이후에 언더스코어 2개를 넣어줍니다.
CREATE TABLE language (
  id              INT     UNSIGNED    NOT NULL    AUTO_INCREMENT,
  name            VARCHAR(100)        NOT NULL,
  code            VARCHAR(50)         NOT NULL,
  lcid            VARCHAR(50)         NOT NULL,
  PRIMARY KEY (id)
);
CREATE UNIQUE INDEX uix_language_01 ON language (lcid);

3-2. migration/V3__Create_worker.sql 파일 생성

CREATE TABLE worker (
    id                  INT     UNSIGNED    NOT NULL    AUTO_INCREMENT,
    password            VARCHAR(500)        NOT NULL,
    name                VARCHAR(500)        NOT NULL,
    email               VARCHAR(255)        NOT NULL,
    creator_id          INT     UNSIGNED    NOT NULL,
    date_created        DATETIME            NOT NULL    DEFAULT CURRENT_TIMESTAMP,
    last_updator_id     INT     UNSIGNED    NOT NULL,
    last_updated        DATETIME            NOT NULL    DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

3-3. seed/V2__Insert_language.sql 파일 생성

INSERT INTO language (name, code, lcid)
VALUES
('English - United States', 'en', 'en-us'),
('French - Switzerland', 'fr', 'fr-ch'),
('Korean', 'ko', 'ko'),
('Spanish - Mexico', 'es', 'es-mx');

 

4. 마이그레이션 상태 확인

flyway info

아직 migrate하지 않았기 때문에 Pending입니다.

 

5. 마이그레이트

flyway migrate

 

서로 다른 폴더에 있었던 sql파일이지만 버전명의 순서대로 마이그레이트 된 것을 확인할 수 있습니다.

flyway info

Success!

 

6. 롤백

무료 버전에서는 지원하지 않습니다. 그냥 sql파일을 생성해주세요.

6-1. migration/V4__Drop_worker.sql 파일 생성

DROP TABLE worker;

 

6-2. 마이그레이트 실행

flyway migrate

worker 테이블이 삭제됩니다.

 

7. Validation

이미 적용된 마이그레이션의 유효성을 검증합니다. 변경사항이 발생한 경우 validate에 실패합니다.

  1. migration/V3__Create_worker.sql에서 "PRIMARY KEY (id)" 부분을 삭제합니다.
  2. validate 실행
    flyway validate

 

8. Repair

sql파일에 변경사항이 발생하면 migration_history테이블의 체크섬이 달라지고 이것을 수정하는 명령어입니다.

8-1. 7번 Validation 오류 수정하기

*주의사항
    7번 validation 항목에서 삭제한 "PRIMARY KEY (id)"가 적용되지 않습니다.
  단지 체크섬만 갱신될 뿐입니다.
  따라서 실제로 "PRIMARY KEY (id)"를 삭제하고 싶다면 초기화 후 다시 migrate 하거나 테이블을 수정하는 sql파일을 생성하고 migrate 해야 합니다.

flyway repair
flyway validate

 

8-2. sql파일이 삭제된 경우

migration/V4__Drop_worker.sql 파일을 삭제합니다.

flyway repair
flyway info

파일이 삭제되었기 때문에 이를 migration_history테이블에 기록합니다.

 

9. Baseline

기존에 사용하던 데이터베이스에 flyway를 적용하고자 하는 경우, 기존의 데이터베이스는 무시하고 flyway를 적용할 기준점을 만듭니다.

flyway baseline

 

10. 초기화

flyway clean

스키마까지 깨끗하게 지워집니다.

 

Liquibase

  • 특징
    1. xml, json, yml, json 등 지원합니다.
    2. changeLogFile파일을 liquibase hub에 등록 가능합니다.
    3. sql 파일명 규칙이 없습니다.
  • 장점
    1. rollback 기능
    2. 두 개의 db를 비교하여 차이점 볼 수 있음. 예) 배포서버와 로컬 비교
    3. 기존 데이터베이스에서 snapshot으로 sql쿼리를 자동생성
  • 단점
    1. 지정한 스키마가 생성되어 있지 않으면 접속할 수 없습니다. -> 따로 생성 해야합니다.
    2. 다른 폴더에 저장되어 있으면 읽어오는 폴더 순서대로 실행됩니다.
    3. sql파일에 -- liquibase formatted sql 과 같은 코멘트를 반드시 적어야 합니다.
    4. 문서에 적힌 대로 해도 한 번에 성공하는 경우가 없고 많은 시행착오가 필요합니다.

 

1. 설치

윈도우 : https://liquibase.org/download

맥/리눅스

brew install liquibase

 

2. liquibase.properties 생성

폴더 구성

제가 필요한 설정만 아래에 적용했습니다.
자세한 사항은 링크를 참조하세요.
https://docs.liquibase.com/workflows/liquibase-community/creating-config-properties.html

changeLogFile: dbchangelog.xml
url:  jdbc:mariadb://127.0.0.1:3306/mydb
username:  root
password:  my-secret-pw
driver: org.mariadb.jdbc.Driver
defaultSchemaName: mydb

 

3. 마이그레이트

liquibase에는 migration 파일을 생성하는 다양한 방법(xml, json, sql, ...)이 있지만 여기서는 sql파일을 분리해서 관리하는 방법을 적었습니다.

3-1. mydb 생성

마이그레이트 하기 전에 mydb를 생성해주셔야 합니다.

생성하지 않으면 오류가 발생하기 때문입니다. flyway는 자동 생성해주지만 liquibase는 아닙니다.

$ docker exec -it mariadb bash          # 터미널
root@84e30b94dc00:/# mysql -uroot -p    # 도커 내부 터미널
Enter password:                         # 루트 비밀번호 입력
MariaDB [(none)]> CREATE DATABASE mydb; # mydb 생성

 

3-2. dbchangelog.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: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-4.1.xsd
    http://www.liquibase.org/xml/ns/pro
    http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd">
    <includeAll  path="migration"/>
    <includeAll  path="seed"/>
</databaseChangeLog>

includeAll path 부분을 보시면 됩니다. sql이 저장되는 폴더를 지정할 수 있습니다.

 

3-3. sql 파일 생성

sql파일은 flyway에서 사용한 파일에 몇 가지 코멘트를 추 기해주어 야합니다.

파일명 규칙은 없습니다만 그대로 사용했습니다.

-- rollback 코멘트 뒤에 오는 sql문은 rollback 명령어가 실행될 때 적용됩니다.

때문에 적어주지 않으면 rollback 할 때 오류가 발생할 수 있습니다.

 

migration/V1__Create_language.sql

-- liquibase formatted sql

-- changeset liquibase:1
CREATE TABLE language (
  id              INT     UNSIGNED    NOT NULL    AUTO_INCREMENT,
  name            VARCHAR(100)        NOT NULL,
  code            VARCHAR(50)         NOT NULL,
  lcid            VARCHAR(50)         NOT NULL,
  PRIMARY KEY (id)
);
CREATE UNIQUE INDEX uix_language_01 ON language (lcid);
-- rollback drop table language;

migration/V3__Create_worker.sql

-- liquibase formatted sql

-- changeset liquibase:3
CREATE TABLE worker (
    id                  INT     UNSIGNED    NOT NULL    AUTO_INCREMENT,
    password            VARCHAR(500)        NOT NULL,
    name                VARCHAR(500)        NOT NULL,
    date_created        DATETIME            NOT NULL    DEFAULT CURRENT_TIMESTAMP,
    last_updator_id     INT     UNSIGNED    NOT NULL,
    last_updated        DATETIME            NOT NULL    DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);
-- rollback drop table worker;

seed/V2__Insert_language.sql

-- liquibase formatted sql

-- changeset liquibase:2
INSERT INTO language (name, code, lcid)
VALUES
('English - United States', 'en', 'en-us'),
('French - Switzerland', 'fr', 'fr-ch'),
('Korean', 'ko', 'ko'),
('Spanish - Mexico', 'es', 'es-mx');
-- rollback DELETE FROM language WHERE id IN (SELECT id FROM language ORDER BY id);

 

3-4. liquibase update

liquibase update

hub 등록하라고 나오는데 엔터를 눌러서 스킵합니다.

 

파일명 규칙이 없기 때문에 불러온 폴더 순서로 마이그레이션 됩니다.

 

4. 상태 확인

liquibase status --verbose

 

5. 롤백

rollback에는 2가지 방법이 있습니다.

5-1. 지정한 횟수만큼 되돌리기

liquibase rollbackCount 1

5-2. 현재 상태에 태그를 붙여서 나중에 되돌아오기

liquibase tag aaaa
liquibase update
liquibase rollback aaaa

해당 태그명은 DATABASECHANGELOG테이블에서도 확인할 수 있습니다.

 

6. Snapshot

6-1. 현재 데이터베이스의 테이블을 create문으로 만들기

liquibase --changeLogFile=mydatabase_changelog.mariadb.sql generateChangeLog

6-2. 현재 데이터베이스의 데이터를 Insert문 및 csv 파일로 가져오기

liquibase --changeLogFile=data.mariadb.sql  --dataOutputDirectory=./csv --diffTypes=data generateChangeLog

 

7. 두 테이블 비교하기

7-1. liquibase.properties에 비교대상 접속 정보 추가

referenceUrl=jdbc:mariadb://127.0.0.1:3306/flyway
referenceUsername=root
referencePassword=my-secret-pw

7-2. diff 커맨드 실행

liquibase diff

8. 초기화

모든 테이블을 drop 합니다. 다만 버그가 있는 것 같습니다.

dropAll 이후에 update를 실행하면 데이터베이스를 찾을 수 없다는 에러가 나옵니다.

데이터베이스를 삭제하고 재생성하는 방법밖에 답을 찾지 못했습니다.

liquibase dropAll

 

형상관리툴 사용 시 규칙

1. 이미 적용한 sql파일은 가능한 수정하지 않도록 합니다. (수정한다면 DB를 제거하고 새로 만드는 것이 낫습니다.)

2. sql파일은 테이블 단위로 생성하는 것이 좋습니다.

3. 버전명은 yyyyMMddHHmmss로 정하면 언제 작성한 파일인지 알기 쉽습니다.

 

결론

저는 Flyway를 사용하기로 했습니다.

Liquibase는 무료 범위에서 다양한 기능을 제공하지만 사용할 때 스트레스가 심하고, 동작이 매끄럽게 진행되지 않았습니다.

당연히 이 글에 소개되지 않은 기능도 많이 있습니다.

Liquibase가 동작만 잘한다면 이상적인 툴이라고 생각하지만, 안정성이 있는 Flyway가 좋다고 판단했습니다.

Ruby on Rails에서는 기본으로 제공될 뿐만 아니라 훨씬 쉽고 잘 동작하는 기능인데 새삼 그리워지는군요.

'개발 > 기타' 카테고리의 다른 글

[CloudFlare] 비HTML의 CDN이용에 관하여  (0) 2022.02.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함