본문 바로가기
  • 기억의 유한함을 기록의 무한함으로✍️            예비 개발자가 꿈꾸는 공간 여기는 안나의 개발 블로그 💻
Programming/DataBase

[Database] 물리적 백업하기 ! , 풀백업 + 증분백업 (mariabackup)

by 제가안난데여♪(´ε`*) 2024. 6. 14.
728x90

1. Test DB 생성 및 mariabackup 설치

  • Test DB 생성

      -- 데이터 베이스 생성
      CREATE DATABASE IF NOT EXISTS test;
      USE test;
      -- 테이블 생성
      CREATE TABLE IF NOT EXISTS test (
          id INT AUTO_INCREMENT PRIMARY KEY,
          name VARCHAR(255) NOT NULL
      );
      -- 데이터 추가
      INSERT INTO test (name) VALUES
      ('John'),
      ('Alice'),
      ('Bob'),
      ('Emily'),
      ('Michael');
      -- 데이터 확인
      SELECT * FROM test;
  • mariabackup 설치

      //Centos
      sudo yum install MariaDB-backup
      //Ubuntu
      sudo apt-get install mariadb-backup
    
  • mariabackup 설치 확인

    
      [user@192 ~]$ mariabackup --version
      mariabackup based on MariaDB server 10.6.18-MariaDB Linux (x86_64)

2. 전체 백업 후 복원

  • 백업할 데이터를 저장할 디렉토리를 생성

    mariabackup 으로 풀백업을 할 경우 백업한 데이터를 저장해 둘 디렉토리는 빈 폴더여야 한다. 경로는 알아서 적당한 곳에 놓으면 된다.

      mkdir backup_full
  • 바이너리 로그 파일 설정

    시점복구(Point-in-Time Recovery, PITR)를 위해서는 bin 파일 설정이 되어 있어야 한다.

    /etc/my.cnf.d/server.cnf 파일에서 아래와 같이 내용을 추가한다.

      [mysqld]
      ...
      log-bin=mysql-bin
      ...

    그리고 systemctl restart mariadb 명령으로 mariadb 서비스를 재시작한다.

    그러면 [mysqld] 에 세팅해준 datadir 경로 또는 설정을 안했다면 ' /var/lib/mysql ' 경로에 아래와 같이 bin 파일이 생성됨을 확인 할 수 있다.
    log-bin 설정을 원하는 이름 변경하여 바이너리 디렉토리 이름을 변경할 수도 있다.

    시점복구(Point-in-Time Recovery, PITR)란?
    시점복구는 데이터베이스가 특정 시점으로 복구 될 수 있도록 하는 기능으로 바이너리 로그 파일을 사용하여 백업 이후의 모든 트랜잭션을 재적용함으로써 데이터베이스를 원하는 시점으로 상태를 되돌릴 수 있다.
    이때, 바이너리 로그파일은 백업 이후의 모든 변경 사항을 기록 하고 있기 때문에 추후 재적용할때 사용할 수 있다.
    또한 바이너리 설정 이후 mariabackup 을 실행하면 생성되는 파일인 xtrabackup_binlog_info 파일에는 아래와 같이 기록 되어 있을 수 있다.
    mysql-bin.000003 12345
    이 정보는 백업 시점의 바이너리 로그 파일과 포지션(바이너리 로그 내, 특정 트랜잭션이나 이벤트가 기록된 위치)을 의미하며 백업 이후의 바이너리 로그를 활용하여 12345 포지션부터 특정 시점까지의 트랜잭션을 재적용할 수 있다.

  • 전체 백업

      mariabackup --backup \
                              --no-lock \ #TABLE LOCK없애기
                              --target-dir=db_backup/backup_full \ #백업한 데이터를 저장해 둘 디렉토리 경로
                              --user=root \ #DB 계정
                              --password=password #DB 비밀번호

    서비스 중인 테이블이 백업으로 인해서 접근이 잠기는 것을 막기 위해 no-lock 옵션을 추가한다.

    위 명령어를 실행하면 아래와 같이 백업 로그가 쭉 찍히고 백업 시점의 바이너리 파일의 포지션도 확인할 수 있다.

    마지막 Completed ok! 백업이 성공적으로 되었다!

target-dir 로 지정했던 디렉토리를 살펴 보면 아래와 같이 폴더들이 생성되어 있음을 확인 할 수 있다.
![](https://velog.velcdn.com/images/dksek3050/post/29077996-0a25-4217-95da-ff441f2c7492/image.png)
  • xtrabackup_info

      [root@192 backup_full]# cat xtrabackup_info 
      uuid = 가림
      name = 
      tool_name = mariabackup
      tool_command = --backup --no-lock --target-dir=db_backup/backup_full --user=root --password=
      tool_version = 10.6.18-MariaDB
      ibbackup_version = 10.6.18-MariaDB
      server_version = 10.6.17-MariaDB-log
      start_time = 2024-05-22 11:35:10
      end_time = 2024-05-22 11:35:13
      lock_time = 1716345313
      binlog_pos = filename 'mysql-bin.000001', position '328', GTID of the last change ''
      innodb_from_lsn = 0
      innodb_to_lsn = 1234712
      partial = N
      incremental = N
      format = file
      compressed = N
    • uuid: 이 백업의 고유 식별자(UUID)이다. 각 백업마다 고유한 식별자를 가지므로, 백업을 구별하는 데 사용된다.
    • name: 백업 이름을 지정할 수 있으나, 이 경우에는 지정되지 않음
    • tool_name: 백업을 수행한 도구의 이름
    • tool_command: 백업을 수행할 때 사용된 명령어.
    • tool_version: 백업 도구의 버전
    • ibbackup_version: InnoDB 백업 도구의 버전
    • server_version: 백업된 데이터베이스 서버의 버전
    • start_time: 백업이 시작된 시간
    • end_time: 백업이 완료된 시간
    • lock_time: 백업 도중에 데이터베이스를 잠근 시간(초) -no-lock 옵션을 사용했기 때문에, 이 값은 의미가 없음
    • binlog_pos: 백업 시점의 바이너리 로그 파일과 위치. 이 값은 시점 복구(Point-in-Time Recovery, PITR)를 위해 중요
    • innodb_from_lsn: 백업의 시작 LSN(Log Sequence Number). 여기서는 전체 백업이므로 0
    • innodb_to_lsn: 백업의 끝 LSN(Log Sequence Number). 이 값은 백업된 데이터의 마지막 LSN
    • partial: 부분 백업인지 여부. N은 전체 백업을 의미
    • incremental: 증분 백업인지 여부입니다. N은 전체 백업을 의미.
    • format: 백업 형식. 여기서는 파일 형식.
    • compressed: 백업이 압축되었는지 여부. N은 압축되지 않았음을 의미
  • xtrabackup_binlog_info

      [root@192 backup_full]# cat xtrabackup_binlog_info 
      mysql-bin.000001        328

    바이너리 파일을 설정하면 생성되는 파일이다.

    데이터 복구를 할때 시점복구의 기준점으로 활용되는 정보를 알려주며 mysql-bin.000001 파일의 325 포지션까지 백업이 완료 됐다는 의미이다.

  • 백업 데이터 반영 ( redo 파일 합치기) --prepare

      mariabackup --prepare \
                  --target-dir=db_backup/backup_full # 전체 백업 디렉토리 경로

    백업할 데이터가 많아서 백업이 1시간 이렇게 걸려버리면 백업된 데이터에 대해서 데이터 무결성이 보장되지 못하게 된다.

    백업을 수행하는 동안 발생된 트랜잭션은 InnoDB 엔진이 관리하는 redo 로그파일에 기록된다. 이 로그 파일이 바로 ib_logfile0 이다.

    백업을 수행할 때 생성되는 파일들 중 하나이며 /var/lib/mysql/ 경로에서도 확인할 수 있다.

    —prepare 옵션을 활용하여 백업 중에 발생된 트랜잭션을 백업 데이터에 수행시켜 데이터의 무결성을 보장한다.

    prepare 실행 후 ib_logfile0 확인해보면 크기가 0byte로 변경됨을 확인 할 수 있다.

  • 복원

    이제 복원을 해보자. 먼저 mariadb 서비스를 종료해야한다.

      systemctl stop mariadb

    /var/lib/mysql 을 삭제할 건데 이전에 혹시 모르니 복사해두자.

      cp -r /var/lib/mysql ./mysql_backup

    그리고 /var/lib/mysql 파일을 모두 지우자.

    우리가 이전에 백업을 저장해둔 파일로 복원을 시킬건데 이때 경로를 지정하지 않아도 자동으로 /var/lib/mysql 로 복원 시키게 된다. 이때 /var/lib/mysql 디렉토리가 빈 디렉토리여야지만 복원이 가능하므로 삭제하자.

      rm -rf /var/lib/mysql/

    준비된 백업 파일로 데이터베이스를 복원해보자.

      mariabackup --copy-back \
                              --target-dir=db_backup/backup_full #복원 시킬 디렉토리 경로

    /var/lib/mysql 의 파일 권한을 root 에서 mysql 로 변환해줘야 한다.

      chown -R mysql:mysql /var/lib/mysql

    복원 끝~!

    mariadb를 다시 실행해보자

      sudo systemctl start mariadb

잘 복원됐다 ! 

3. 증분 백업

물리적 백업 도구로 전체 백업 후 복원까지 해보았다.

전체 백업 후 데이터를 추가 한 후 증분 백업을 하고 또 데이터를 추가 한 후 증분 백업을 한 후에 복원까지 해보겠다.

전체 백업 → 첫번째 증분백업 → 두번째 증분백업 → 복원

  • 전체 백업

    전체 백업 과정은 위와 동일하니 자세히 설명하지 않겠다.

    다만 생성된 xtrabackup_checkpoints 파일을 살펴보면
    lsn( 로그 시퀀스 번호) 에 대한 정보가 담겨 있다.

1.from_lsn:
- from_lsn은 백업 작업의 시작 LSN(Log Sequence Number)을 나타냅니다.
- 이 값은 백업 작업이 시작되는 시점의 데이터베이스 로그의 위치를 나타냅니다.
- 여기서는 0으로 설정되어 있어, 백업이 시작된 지점부터 데이터베이스 로그를 기록했음을 의미합니다.
2. to_lsn:
- to_lsn은 백업 작업의 끝 LSN(Log Sequence Number)을 나타냅니다.
- 이 값은 백업 작업이 종료되는 시점의 데이터베이스 로그의 위치를 나타냅니다.
- 여기서는 1242124로 설정되어 있어, 백업 작업이 종료된 시점의 데이터베이스 로그 위치를 가리킵니다.
3. last_lsn:
- last_lsn은 백업 작업에서 가장 최근의 로그 이벤트를 나타냅니다.
- 이 값은 백업 작업에서 가장 최근에 처리된 데이터베이스 로그의 위치를 나타냅니다.
- 여기서는 12450676로 설정되어 있어, 백업 작업에서 가장 최근에 처리된 데이터베이스 로그의 위치를 가리킵니다.

이 lsn 번호를 사용하여 백업에 반영된 트랜잭션을 확인한다.
  • 첫번째 증분백업

    증분 백업 전 아래와 같이 6번 데이터를 추가해주었다.

      INSERT INTO `test`.`test` (`id`, `name`) VALUES ('6', 'first inc');

back_inc1 이라는 디렉토리를 생성 후 증분백업을 진행해주었다.

```bash
mariabackup --backup \
                        --no-lock \ #TABLE LOCK없애기
                        --target-dir=db_backup/backup_inc1 \ #증분백업한 데이터를 저장해 둘 디렉토리 경로
                        --incremental-basedir=db_backup/backup_full \ #LSN을 참조할 경로 (즉, 이전에 백업한 디렉토리 경로)
                        --user=root \ #DB 계정
                        --password=password #DB 비밀번호
```

전체 백업과 다른 점은 **`--**incremental**-**basedir=db_backup/backup_full`옵션을 추가 했다. 이전 전체 백업이 저장된 디렉토리를 지정하는 옵션이다.

이 디렉토리를 기준으로 그 이후 변경사항만 백업한다.

그리고 로그를 살펴보면   `incremental backup from 1242124 is enabled.`  전체 백업때 `to_lsn` 이었던 1242124 기준으로 증분 백업이 활성화 되었고 이 lsn 을 기준으로 변경된 내용만 백업 한다는 것을 의미한다.
  • 두번째 증분백업

    증분 백업 전 아래와 같이 7번 데이터를 추가해주었다.

      INSERT INTO `test`.`test` (`id`, `name`) VALUES ('7', 'second inc');

    back_inc2 이라는 디렉토리를 생성 후 증분백업을 진행해주었다.

      mariabackup --backup \
                              --no-lock \ #TABLE LOCK없애기
                              --target-dir=db_backup/backup_inc2 \ #증분백업한 데이터를 저장해 둘 디렉토리 경로
                              --incremental-basedir=db_backup/backup_inc1\ #LSN을 참조할 경로 (즉, 이전에 백업한 디렉토리 경로)
                              --user=root \ #DB 계정
                              --password=password #DB 비밀번호

    전체, 첫번째 증분, 두번째 증분 백업 파일의 xtrabackup_binlog_info 파일의 내용을 살펴보면 점차 바이너리 파일의 정보에 적힌 번호가 증가함을 알 수 있다.

    번호가 클 수록 더 나중 정보를 가지고 있다는 의미이다.

3. 복원

전체 백업 - 첫번째 증분백업 - 두번째 증분백업

이렇게 세 단계의 백업을 진행했고

백업한 데이트를 이용하여 복원을 할 것이다.

전체 백업 데이터는 리두 로그 파일을 합쳤고

두번째, 세번째 백업 데이터는 전체 백업 데이터에 리두 로그 파일을 반영하지 않았다.

복원 시나리오는 첫번째 백업 까지 복원해보고 두번째 백업까지 복원해볼 것이다.

총 두번

복원 과정은 전체 백업 데이터를 복원 하는 것과 완전히 동일하다

복원 하는 데이터도 전체 백업 데이터가 타겟이다.

다른 점은 복원 하기 전 복원 준비 과정 (--prepare ) 에서 증분백업 데이터에서 전체 백업 데이터로 redo 로그 파일을 반영한다는 점이다.

  • 복원 준비

      mariabackup --prepare --target-dir=db_backup/backup_full --incremental-dir=db_backup/backup_inc1

    ib_logfile0 이 초기화 된다 (파일의 사이즈가 0으로 바뀜)

전체, 증분1, 증분2 백업 파일으 xtrabackup_binlog_info 파일 살펴보면 

원래는 4309 바이너리 로그번호를 가졌던 전체 백업은 증분1 백업과 동일한 로그 번호로 변경 되었고 아직 --prepare 작업을 하지 않은 inc2 는 변경사항이 없다.
  • 복원

      # mariadb 서버 중지
      sudo systemctl stop mariadb
      # /var/lib/mysql 복사 후 삭제
      cp -r  /var/lib/mysql ./mysql_backup_full
      # 복원
      mariabackup --copy-back --target-dir=db_backup/backup_full
      # 데이터 디렉토리 권한 설정
      sudo chown -R mysql:mysql /var/lib/mysql
      # mariadb 서버 재시작 
      sudo systemctl start mariadb
    

복원 완료

기존에 7번 second inc 까지 존재했는데 6번까지 존재했던 증분백업까지 복원 시키니 7번은 확인 되지 않는다. 두번째 백업파일 복원도 해보자

두번째 백업파일도 복원해보자 과정은 동일하니 적지 않겠다.

2. 🎇운영 서버에 증분백업 설정🎇


1. 백업 시나리오

  • 디렉토리 구조

      backup/db
       ├ yyyy-mm-dd # 월요일의 날짜
       |  ├ yyyy-mm-dd-HH-MM-SS-full # 월요일 풀백업
       |  ├ yyyy-mm-dd-HH-MM-SS-inc # 화요일 증분백업
       |  ├ yyyy-mm-dd-HH-MM-SS-inc # 수요일 증분백업
       |  ├ yyyy-mm-dd-HH-MM-SS-inc # 목요일 증분백업
       |  ├ yyyy-mm-dd-HH-MM-SS-inc # 금요일 증분백업
       |  ├ yyyy-mm-dd-HH-MM-SS-inc # 토요일 증분백업
       |  └ yyyy-mm-dd-HH-MM-SS-inc # 일요일 증분백업
       |  
       ├ log # 주간 단위로 압축 파일 저장 디렉토리
       |  └ backup.log
       |  
       ├ script # 스크립트 디렉토리
       |  ├ full_backup_start.sh # 풀백업 스크립트 (월요일 실행)
       |  ├ increment_backup_start.sh # 증분백업 스크립트 (월요일만 제외하고 실행)
       |  └ compression.sh # 백업 주간 압축 스크립트 (일요일 증분 백업 후 실행)
       |
       ├ yyyy-mm-01.tar.gz  # 주간 단위로 압축 파일 저장 디렉토리
       ├ yyyy-mm-08.tar.gz
       └ yyyy-mm-15.tar.gz
    
  • 시나리오
    • 매주 월요일 자정 전체 백업을 실행 - /backup/db/yyyy-mm-dd-HH-MM-SS-full
    • 매주 화, 수, 목, 금, 토, 일 자정 월요일 전체백업을 베이스로 하여 증분 백업 실행 - /backup/db/yyyy-mm-dd-HH-MM-SS-inc
    • 매주 일요일 자정 증분백업 마친 후 해당 주 압축 - /backup/db/yyyy-mm-dd.tar.gz
    • 압축된 기존 파일들은 삭제
    • 만일 월요일에 전체 백업된 파일이 없다면 전체 백업을 실행한다.
    • 베이스 백업이 비정상이여서 백업이 안될 수 있는 가능성을 고려해 백업이 비정상 적으로 끝나면 정상적으로 마칠 때까지 모든 백업 파일을 탐색하며 증분백업 할 수 있도록 한다.

2. full_backup_start.sh(전체백업)

#!/bin/bash

# 전체 백업 실행 스크립트

# 로그 파일 경로
log_file="/backup/db/log/backup.log"
day_of_week=""
start_time=0
end_time=0

# 로그 함수 정의
log_message() {
    local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    echo "[$timestamp] $1" >> "$log_file"
}

# 명령 실행 결과 로그 출력 함수 정의
log_command_result() {
    local exit_code=$1
    local action=$2
    local error_log=$3

    if [ $exit_code -eq 0 ]; then
        log_message "       [Success] $action"
    else
        log_message "       [Failed] $action (Exit Code: $exit_code)"
        if [ -n "$error_log" ]; then
            log_message "Error Log: $error_log"
        fi
        exit $exit_code
    fi
}

# 시간 측정 시작 함수
start_timer() {
    start_time=$(date +%s)
}

# 시간 측정 종료 및 경과 시간 계산 함수
end_timer() {
    end_time=$(date +%s)
    elapsed_time=$((end_time - start_time))
}

# 경과 시간을 시/분/초 형식으로 변환하여 출력하는 함수
format_elapsed_time() {
    local total_seconds=$1
    local hours=$((total_seconds / 3600))
    local minutes=$(( (total_seconds % 3600) / 60 ))
    local seconds=$((total_seconds % 60))
    echo "${hours}h ${minutes}m ${seconds}s"
}

# 메인 함수 정의
main() {
    start_timer  # 시작 시간 기록

    # 로그 파일 생성 또는 초기화
    echo "" >> "$log_file"

    log_message "===== [ Full-Backup-Start ] script started at $(date +"%Y-%m-%d %H:%M:%S"). ====="

    # 오늘 날짜의 요일 확인
    day_of_week=$(date +%A)

    # 백업 파일 경로 설정
    if [ "$day_of_week" == "Monday" ]; then
        backup_date=$(date +'%Y-%m-%d')
    else
        backup_date=$(date -d "last Monday" +'%Y-%m-%d')
    fi

    backup_dir="/backup/db/$backup_date"
    full_backup_dir="$backup_dir/$(date +'%Y-%m-%d-%H-%M-%S')-full"

    # 백업 디렉토리 생성
    log_message "1. Attempting to create directory: $backup_dir"
    mkdir -p "$backup_dir"
    log_command_result $? "Creating backup directory"

    # 풀백업 디렉토리 생성
    log_message "2. Attempting to create directory: $full_backup_dir"
    mkdir -p "$full_backup_dir"
    log_command_result $? "Creating full-backup directory"

    # mariabackup 실행
    log_message "3. Starting database full-backups ..."
    mariabackup --backup --no-lock --target-dir="$full_backup_dir"  --user= --password= >> ${log_file} 2>&1
    log_command_result $? "MariaDB full-backup"

    end_timer  # 종료 시간 기록 및 경과 시간 계산
    local elapsed_time_str=$(format_elapsed_time $elapsed_time)

    # 백업 완료 메시지 출력
    log_message "===== [ Full-Backup-Completed ] Full-Backup process completed! Total time: $elapsed_time_str =====
    "
}

# 메인 함수 호출
main

# 메인 함수 호출 이후에 일요일인지 확인
if [ "$day_of_week" == "Sunday" ]; then
    # 일요일인 경우 compressions.sh 실행
    log_message "Today is Sunday. Running compressions.sh script."
    /backup/db/script/compressions.sh
    exit 0
fi

3. increment_backup_start.sh (증분백업)

#!/bin/bash

# 증분 백업 실행 스크립트

# 전역 변수 선언
log_file="/backup/db/log/backup.log"
backup_dir=""
increment_backup_dir=""
incremental_basedir=""
day_of_week=""
start_time=0
end_time=0

# 로그 함수 정의
log_message() {
    local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    echo -e "[$timestamp] $1" >> "$log_file"
}

# 명령 실행 결과 로그 출력 함수 정의
log_command_result() {
    local exit_code=$1
    local action=$2
    local error_log=$3

    if [ $exit_code -eq 0 ]; then
        log_message "       [Success] $action"
    else
        log_message "       [Failed] $action (Exit Code: $exit_code)"
        if [ -n "$error_log" ]; then
            log_message "Error Log: $error_log"
        fi
        exit $exit_code
    fi
}

# 풀 백업 실행 함수
run_full_backup() {
    log_message "       Running the full backup script."
    /backup/db/script/full_backup_start.sh
    exit 0
}

# 증분 백업 디렉토리 생성 함수
create_incremental_backup_dir() {
    increment_backup_dir="$backup_dir/$(date +'%Y-%m-%d-%H-%M-%S')-inc"
    log_message "3. Attempting to create directory: $increment_backup_dir"
    mkdir -p "$increment_backup_dir"
    log_command_result $? "Creating incremental-backup directory"
}

# 증분 베이스 디렉토리 설정 함수
set_incremental_basedir() {
    log_message "4. Checking incremental base directory"

    # 상위 디렉토리를 제외하고 증분 백업 디렉토리 목록을 최신순으로 정렬
    local base_dirs=($(find "$backup_dir" -mindepth 1 -maxdepth 1 -type d | sort -r))

    for dir in "${base_dirs[@]}"; do  # 각 증분 백업 디렉토리에 대해 반복

        # 이번 증분 백업을 위해 생성한 디렉토리는 제외
        if [ "$dir" == "$increment_backup_dir" ]; then
            continue
        fi

        incremental_basedir="$dir"
        log_message "       Set incremental base directory to: $incremental_basedir"

        # 마리아DB 백업 실행
        backup_mariadb
        return_value=$?

        # 마리아DB 백업이 성공한 경우 함수 종료
        if [ $return_value -eq 0 ]; then
            log_command_result $return_value "MariaDB incremental-backup! \n Target-dir : ${increment_backup_dir} \n Incremental-basedir : ${incremental_basedir}"
            return 0
        else
            log_message "       [Failed] MariaDB backup failed for directory: $incremental_basedir Target-dir: ${increment_backup_dir} (Exit Code: $return_value)"
        fi
    done

    # 여기까지 왔다면 모든 증분 백업 시도가 실패한 것
    log_message "       Failed to perform incremental backup in all directories."
    exit $return_value
}

# 마리아DB 백업 함수
backup_mariadb() {
    log_message "5. Starting MariaDB incremental-backup ..."
    mariabackup --backup --no-lock --target-dir="$increment_backup_dir" --incremental-basedir="$incremental_basedir" --user=root --password=패스워드 >> "$log_file" 2>&1
    local result=$?
    return $result
}

# 시간 측정 시작 함수
start_timer() {
    start_time=$(date +%s)
}

# 시간 측정 종료 및 경과 시간 계산 함수
end_timer() {
    end_time=$(date +%s)
    elapsed_time=$((end_time - start_time))
}

# 경과 시간을 시/분/초 형식으로 변환하여 출력하는 함수
format_elapsed_time() {
    local total_seconds=$1
    local hours=$((total_seconds / 3600))
    local minutes=$(( (total_seconds % 3600) / 60 ))
    local seconds=$((total_seconds % 60))
    echo "${hours}h ${minutes}m ${seconds}s"
}

# 메인 함수 정의
main() {

    start_timer  # 시작 시간 기록

    # 로그 파일 생성 또는 초기화
    echo "" >> "$log_file"

    log_message "===== [ Incremental-Backup-Start ] script started at $(date +"%Y-%m-%d %H:%M:%S"). ====="

    # 오늘 날짜의 요일 확인
    day_of_week=$(date +%A)

    # 백업 파일 경로 설정
    if [ "$day_of_week" == "Monday" ]; then
        backup_date=$(date +'%Y-%m-%d')
    else
        backup_date=$(date -d "last Monday" +'%Y-%m-%d')
    fi

    # 1. 백업 디렉토리 확인, 존재하지 않을 시 풀백업 스크립트 실행
    backup_dir="/backup/db/$backup_date"
    log_message "1. Checking backup directory: $backup_dir"
    if [ ! -d "$backup_dir" ]; then
        log_message "       Backup directory does not exist: $backup_dir"
        run_full_backup
    else
        log_message "       ok"
    fi

    # 2. full 백업 디렉토리가 존재하지 않는 경우 풀 백업 스크립트 실행
    local full_backup_dir=$(find "$backup_dir" -maxdepth 1 -type d -name "*full*")
    log_message "2. Checking full-backup directory: $full_backup_dir"
    if [ -z "$full_backup_dir" ]; then
        log_message "       Full backup directory not found"
        run_full_backup
    else
        log_message "       ok"
    fi

    # 3. 증분 백업 디렉토리 생성
    create_incremental_backup_dir

    # 4. 증분 베이스 디렉토리 설정
    set_incremental_basedir

    # 백업 완료 메시지 출력
    # log_message "Incremental-Backup process completed !"

    end_timer  # 종료 시간 기록 및 경과 시간 계산
    local elapsed_time_str=$(format_elapsed_time $elapsed_time)
    # 백업 완료 메시지 출력
    log_message "===== [ Incremental-Backup-Completed ] Incremental-Backup process completed! Total time: $elapsed_time_str =====
    "
}

# 메인 함수 호출
main

# 메인 함수 호출 이후에 일요일인지 확인
if [ "$day_of_week" == "Sunday" ]; then
    # 일요일인 경우 compressions.sh 실행
    log_message "Today is Sunday. Running compressions.sh script."
    /backup/db/script/compressions.sh
    exit 0
fi

4. compressions.sh (압축)

#!/bin/bash

# 주간 압축 실행 스크립트

# 전역 변수 선언
log_file="/backup/db/log/backup.log"
backup_dir=""
start_time=0
end_time=0

# 로그 함수 정의
log_message() {
    local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    echo -e "[$timestamp] $1" >> "$log_file"
}

# 명령 실행 결과 로그 출력 함수 정의
log_command_result() {
    local exit_code=$1
    local action=$2
    local error_log=$3

    if [ $exit_code -eq 0 ]; then
        log_message "       [Success] $action"
    else
        log_message "       [Failed] $action (Exit Code: $exit_code)"
        if [ -n "$error_log" ]; then
            log_message "Error Log: $error_log"
        fi
        exit $exit_code
    fi
}

# 시간 측정 시작 함수
start_timer() {
    start_time=$(date +%s)
}

# 시간 측정 종료 및 경과 시간 계산 함수
end_timer() {
    end_time=$(date +%s)
    elapsed_time=$((end_time - start_time))
}

# 경과 시간을 시/분/초 형식으로 변환하여 출력하는 함수
format_elapsed_time() {
    local total_seconds=$1
    local hours=$((total_seconds / 3600))
    local minutes=$(( (total_seconds % 3600) / 60 ))
    local seconds=$((total_seconds % 60))
    echo "${hours}h ${minutes}m ${seconds}s"
}

# 메인 함수 정의
main() {
    start_timer  # 시작 시간 기록

    # 로그 파일 생성 또는 초기화
    echo "" >> "$log_file"

    log_message "===== [ Copression-Start ] Weekly backup file compression started at $(date +"%Y-%m-%d %H:%M:%S"). ====="

    # 오늘 날짜의 요일 확인
    local day_of_week=$(date +%A)

    # 백업 파일 경로 설정
    if [ "$day_of_week" == "Monday" ]; then
        backup_date=$(date +'%Y-%m-%d')
    else
        backup_date=$(date -d "last Monday" +'%Y-%m-%d')
    fi

    backup_dir="/backup/db/$backup_date"

   log_message "1. Compressing $backup_dir"
    # 압축할 파일 확인
    if [ -d "$backup_dir" ]; then
        # 압축 파일 이름 설정
        local archive_name="${backup_dir}.tar.gz"

        # 디렉토리 압축
        tar -czf "$archive_name" -C "$backup_dir" .
        # 압축된 파일 경로 출력
         log_command_result $? "Compressed file: $archive_name"

        # 압축 성공 시 원본 디렉토리 삭제
        rm -rf "$backup_dir"
        log_command_result $? "Deleting original backup directory $backup_dir"
    else
        log_message "       [Failed] Backup directory $backup_dir does not exist."
        exit 1
    fi

    end_timer  # 종료 시간 기록
    elapsed_time=$(format_elapsed_time $((end_time - start_time)))
    log_message "===== [Compression-End] Weekly backup file compression ended at $(date +"%Y-%m-%d %H:%M:%S"). Elapsed time: $elapsed_time ====="

}

# 메인 함수 호출
main

추가로 데이터가 쌓이면 백업 시간이 얼마나 걸렸는지 확인해야 할 것 같아서 백업에 걸린 시간도 로그에 남길 수 있도록 하였다.

마지막으로 cron 을 활용해 지정한 요일 자정에 스크립트 파일이 실행되어 백업이 실행되도록 설정하였다.







📎 참고 링크

https://wikidocs.net/232618

https://leesumin.tistory.com/82

https://brush-describr.tistory.com/entry/MySQL-MariaBackup-증분-백업-관리하기XtraBackup

http://www.linuxdata.org/bbs/board.php?bo_table=DB&wr_id=24&device=pc

https://graykang.tistory.com/entry/mariabackupFull-Backup-and-Restore-with-Mariabackup

반응형