본문으로 건너뛰기

mysqlhotcopy로 MySQL 데이터베이스를 백업하는 방법은 무엇인가요?

💡 요약 정리

  • mysqlhotcopy는 MySQL 패키지에 포함된 Perl 기반 백업 스크립트입니다.
  • MyISAM 스토리지 엔진만 지원하며, InnoDB는 사용할 수 없습니다.
  • 파일 시스템 레벨 복사 방식으로 매우 빠른 백업 속도를 제공합니다.
  • --allowold 또는 --addtodest 옵션으로 증분 백업이 가능합니다.
  • MySQL 5.7 이후 버전에서는 deprecated 되었으므로 mysqldump나 MySQL Enterprise Backup 사용을 권장합니다.

개요

mysqlhotcopy는 MySQL 패키지에 포함된 Perl로 작성된 백업 스크립트입니다.

주요 특징

  • 빠른 속도: DB 디렉토리를 파일 시스템 레벨에서 직접 복사
  • 간편한 사용: 터미널에서 명령어 한 줄로 백업
  • 테이블 잠금: 백업 중 READ LOCK으로 데이터 일관성 보장

제한 사항

  • MyISAM 전용: MyISAM 스토리지 엔진만 지원
  • InnoDB 미지원: InnoDB 테이블은 백업 불가
  • Same-host 전용: 동일 서버의 디렉토리로만 복사 가능
  • Deprecated: MySQL 5.7부터 deprecated, MySQL 8.0에서 제거됨

1. 데이터베이스 전체 백업

기본 사용법

mysqlhotcopy [db_name] [디렉토리경로]

백업할 DB를 지정한 경로에 디렉토리로 생성하여 복사합니다.

예제

비밀번호 없이 백업 시도 (오류 발생):

[root@localhost bin]# ./mysqlhotcopy mysql /home/jook/mysqlbak

DBI connect(';host=localhost;mysql_read_default_group=mysqlhotcopy','',...) failed:
Access denied for user 'root'@'localhost' (using password: NO) at ./mysqlhotcopy line 197

비밀번호 옵션으로 백업 성공:

[root@localhost bin]# ./mysqlhotcopy --password=XXXX mysql /home/jook/mysqlbak

Flushed 22 tables with read lock (`mysql`.`columns_priv`, `mysql`.`db`, `mysql`.`event`,
`mysql`.`func`, `mysql`.`help_category`, `mysql`.`help_keyword`, `mysql`.`help_relation`,
`mysql`.`help_topic`, `mysql`.`host`, `mysql`.`ndb_binlog_index`, `mysql`.`plugin`,
`mysql`.`proc`, `mysql`.`procs_priv`, `mysql`.`proxies_priv`, `mysql`.`servers`,
`mysql`.`tables_priv`, `mysql`.`time_zone`, `mysql`.`time_zone_leap_second`,
`mysql`.`time_zone_name`, `mysql`.`time_zone_transition`, `mysql`.`time_zone_transition_type`,
`mysql`.`user`) in 0 seconds.
Locked 0 views () in 0 seconds.
Copying 73 files...
Copying indices for 0 files...
Unlocked tables.
mysqlhotcopy copied 22 tables (73 files) in 0 seconds (0 seconds overall).

결과 확인:

[root@localhost bin]# ls -l /home/jook/mysqlbak/
total 4
drwx------ 2 mysql mysql 4096 Feb 21 15:10 mysql

[root@localhost bin]# ls /home/jook/mysqlbak/mysql/
columns_priv.frm     help_relation.frm   procs_priv.MYI      time_zone_name.MYD
columns_priv.MYD     help_relation.MYD   proxies_priv.frm    time_zone_name.MYI
columns_priv.MYI     help_relation.MYI   proxies_priv.MYD    time_zone_name.frm
db.frm               help_topic.frm      proxies_priv.MYI    user.frm
db.MYD               help_topic.MYD      ...

2. 증분 백업

문제: 기존 백업 디렉토리 존재

기존에 백업된 디렉토리가 있으면 오류 발생:

[root@localhost bin]# ./mysqlhotcopy --password=XXX mysql /home/jook/mysqlbak

Can't hotcopy to '/home/jook/mysqlbak/mysql' because directory
already exist and the --allowold or --addtodest options were not given.

해결 방법 1: --allowold 옵션

기존 디렉토리 이름을 _old로 변경하고 새로 백업:

[root@localhost bin]# ./mysqlhotcopy --allowold --password=XXX mysql /home/jook/mysqlbak

Existing hotcopy directory renamed to '/home/jook/mysqlbak/mysql_old'
Flushed 22 tables with read lock (`mysql`.`columns_priv`, `mysql`.`db`, `mysql`.`event`,
`mysql`.`func`, `mysql`.`help_category`, `mysql`.`help_keyword`, `mysql`.`help_relation`,
`mysql`.`help_topic`, `mysql`.`host`, `mysql`.`ndb_binlog_index`, `mysql`.`plugin`,
`mysql`.`proc`, `mysql`.`procs_priv`, `mysql`.`proxies_priv`, `mysql`.`servers`,
`mysql`.`tables_priv`, `mysql`.`time_zone`, `mysql`.`time_zone_leap_second`,
`mysql`.`time_zone_name`, `mysql`.`time_zone_transition`, `mysql`.`time_zone_transition_type`,
`mysql`.`user`) in 0 seconds.
Locked 0 views () in 0 seconds.
Copying 73 files...
Copying indices for 0 files...
Unlocked tables.
mysqlhotcopy copied 22 tables (73 files) in 0 seconds (0 seconds overall).

결과:

[root@localhost bin]# ls /home/jook/mysqlbak/
mysql  mysql_old

해결 방법 2: --addtodest 옵션

기존 백업 디렉토리에 추가 (변경된 파일만 업데이트):

[root@localhost bin]# ./mysqlhotcopy --addtodest --password=XXX mysql /home/jook/mysqlbak

Flushed 22 tables with read lock (`mysql`.`columns_priv`, `mysql`.`db`, `mysql`.`event`,
`mysql`.`func`, `mysql`.`help_category`, `mysql`.`help_keyword`, `mysql`.`help_relation`,
`mysql`.`help_topic`, `mysql`.`host`, `mysql`.`ndb_binlog_index`, `mysql`.`plugin`,
`mysql`.`proc`, `mysql`.`procs_priv`, `mysql`.`proxies_priv`, `mysql`.`servers`,
`mysql`.`tables_priv`, `mysql`.`time_zone`, `mysql`.`time_zone_leap_second`,
`mysql`.`time_zone_name`, `mysql`.`time_zone_transition`, `mysql`.`time_zone_transition_type`,
`mysql`.`user`) in 0 seconds.
Locked 0 views () in 0 seconds.
Copying 73 files...
Copying indices for 0 files...
Unlocked tables.
mysqlhotcopy copied 22 tables (73 files) in 0 seconds (0 seconds overall).

참고:

  • 매뉴얼에는 --allowold_old 디렉토리를 생성한다고 되어 있으나, 일부 버전에서는 --addtodest와 동일하게 동작
  • 증분 백업 시 변경된 파일만 업데이트하여 백업 시간 단축

3. 특정 테이블 백업

사용법

mysqlhotcopy [db_name./table_name/] [디렉토리경로]

백업할 테이블을 DB명./테이블명/ 형식으로 지정합니다.

예제

user 테이블만 백업:

[root@localhost bin]# ./mysqlhotcopy --password=XXX mysql./user/ /home/jook/mysqlbak/

Flushed 1 tables with read lock (`mysql`.`user`) in 0 seconds.
Locked 0 views () in 0 seconds.
Copying 3 files...
Copying indices for 0 files...
Unlocked tables.
mysqlhotcopy copied 1 tables (3 files) in 0 seconds (0 seconds overall).

백업 결과 확인:

[root@localhost bin]# cd /home/jook/mysqlbak/mysql
[root@localhost mysql]# ls
user.MYD  user.MYI  user.frm

[root@localhost mysql]# ls -lh
total 12K
-rw-rw---- 1 mysql mysql 1.2K Feb 21 15:15 user.MYD
-rw-rw---- 1 mysql mysql 2.0K Feb 21 15:15 user.MYI
-rw-rw---- 1 mysql mysql 8.0K Feb 21 15:15 user.frm

파일 설명:

  • .frm: 테이블 구조 정의 파일
  • .MYD: 테이블 데이터 파일 (MyISAM Data)
  • .MYI: 테이블 인덱스 파일 (MyISAM Index)

4. 여러 데이터베이스 백업

한 번에 여러 DB 백업

# 공백으로 구분하여 여러 DB 지정
mysqlhotcopy --password=XXX db1 db2 db3 /backup/mysql/

정규표현식 사용

# test로 시작하는 모든 DB 백업
mysqlhotcopy --password=XXX --regexp=^test /backup/mysql/

5. 백업 복원

복원 방법

mysqlhotcopy로 백업한 데이터는 파일 시스템 레벨 복사이므로, 복원도 파일 복사로 수행합니다.

복원 절차:

# 1. MySQL 서비스 중지
service mysqld stop

# 2. 기존 DB 디렉토리 백업 (안전을 위해)
mv /var/lib/mysql/mydb /var/lib/mysql/mydb_old

# 3. 백업 디렉토리를 MySQL 데이터 디렉토리로 복사
cp -r /backup/mysql/mydb /var/lib/mysql/

# 4. 권한 설정
chown -R mysql:mysql /var/lib/mysql/mydb
chmod -R 660 /var/lib/mysql/mydb/*
chmod 700 /var/lib/mysql/mydb

# 5. MySQL 서비스 시작
service mysqld start

특정 테이블만 복원

# MySQL 서비스가 실행 중일 때도 가능

# 1. 테이블 삭제 (MySQL 클라이언트에서)
mysql> USE mydb;
mysql> DROP TABLE user;

# 2. 백업 파일 복사 (Shell에서)
cp /backup/mysql/mydb/user.* /var/lib/mysql/mydb/

# 3. 권한 설정
chown mysql:mysql /var/lib/mysql/mydb/user.*
chmod 660 /var/lib/mysql/mydb/user.*

# 4. 테이블 사용 가능 여부 확인 (MySQL 클라이언트에서)
mysql> FLUSH TABLES;
mysql> SELECT * FROM user LIMIT 1;

6. 주요 옵션

인증 옵션

옵션설명예제
--user=usernameMySQL 사용자명--user=root
--password=passMySQL 비밀번호--password=secret
--port=portMySQL 포트--port=3306
--socket=pathSocket 파일 경로--socket=/tmp/mysql.sock

백업 옵션

옵션설명동작
--allowold기존 백업 디렉토리를 _old로 변경/backup/db/backup/db_old
--addtodest기존 백업에 추가 (증분 백업)변경된 파일만 업데이트
--checkpoint=name체크포인트 생성증분 백업 기준점 설정
--flushlog백업 후 로그 플러시Binary log rotate
--keepold_old 디렉토리 유지이전 백업 보존
--method=method복사 방법 지정cp, scp
--quiet메시지 최소화로그 출력 감소
--regexp=pattern정규표현식으로 DB 선택--regexp=^test

예제

플러시 로그와 함께 백업:

mysqlhotcopy --password=XXX --flushlog mydb /backup/mysql/

체크포인트 생성:

mysqlhotcopy --password=XXX --checkpoint=daily mydb /backup/mysql/

조용한 모드 (Quiet):

mysqlhotcopy --password=XXX --quiet mydb /backup/mysql/

7. 백업 자동화

cron을 이용한 정기 백업

/etc/cron.d/mysql-backup 생성:

# 매일 새벽 2시에 백업
0 2 * * * root /usr/bin/mysqlhotcopy --password=XXXX --flushlog --allowold mydb /backup/mysql/ >> /var/log/mysql-backup.log 2>&1

백업 스크립트

/usr/local/bin/mysql-hotcopy-backup.sh:

#!/bin/bash
# MySQL Hot Copy Backup Script

# 설정
MYSQL_USER="root"
MYSQL_PASS="your_password"
BACKUP_DIR="/backup/mysql"
LOG_FILE="/var/log/mysql-backup.log"
RETENTION_DAYS=7

# 날짜별 백업 디렉토리
DATE=$(date +%Y%m%d)
BACKUP_PATH="${BACKUP_DIR}/${DATE}"

# 백업 시작
echo "========================================" >> $LOG_FILE
echo "Backup started at $(date)" >> $LOG_FILE

# 디렉토리 생성
mkdir -p $BACKUP_PATH

# 백업 대상 DB 목록
DBS="db1 db2 db3"

for DB in $DBS; do
    echo "Backing up database: $DB" >> $LOG_FILE
    /usr/bin/mysqlhotcopy \
        --user=$MYSQL_USER \
        --password=$MYSQL_PASS \
        --flushlog \
        $DB \
        $BACKUP_PATH >> $LOG_FILE 2>&1

    if [ $? -eq 0 ]; then
        echo "✓ $DB backup completed" >> $LOG_FILE
    else
        echo "✗ $DB backup failed" >> $LOG_FILE
    fi
done

# 압축
echo "Compressing backup..." >> $LOG_FILE
cd $BACKUP_DIR
tar -czf ${DATE}.tar.gz ${DATE}/
rm -rf ${DATE}

# 오래된 백업 삭제
echo "Removing old backups (older than $RETENTION_DAYS days)..." >> $LOG_FILE
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete

echo "Backup completed at $(date)" >> $LOG_FILE
echo "========================================" >> $LOG_FILE

권한 설정 및 cron 등록:

chmod +x /usr/local/bin/mysql-hotcopy-backup.sh

# crontab 등록
crontab -e

# 매일 새벽 2시 실행
0 2 * * * /usr/local/bin/mysql-hotcopy-backup.sh

8. 문제 해결

"Access denied" 오류

오류 메시지:

DBI connect(...) failed: Access denied for user 'root'@'localhost' (using password: NO)

해결 방법:

# 1. 비밀번호 옵션 추가
mysqlhotcopy --password=XXXX mydb /backup/mysql/

# 2. my.cnf에 비밀번호 저장 (권장하지 않음)
vi /root/.my.cnf

[mysqlhotcopy]
user=root
password=your_password

chmod 600 /root/.my.cnf

"Can't hotcopy ... directory already exist" 오류

오류 메시지:

Can't hotcopy to '/backup/mysql/mydb' because directory already exist
and the --allowold or --addtodest options were not given.

해결 방법:

# 방법 1: 기존 디렉토리 삭제
rm -rf /backup/mysql/mydb

# 방법 2: --allowold 옵션 사용
mysqlhotcopy --allowold --password=XXX mydb /backup/mysql/

# 방법 3: --addtodest 옵션 사용 (증분 백업)
mysqlhotcopy --addtodest --password=XXX mydb /backup/mysql/

InnoDB 테이블 백업 불가

오류 메시지:

mysqlhotcopy can only handle MyISAM tables

해결 방법:

InnoDB 테이블은 mysqlhotcopy를 사용할 수 없습니다. 다음 대안을 사용하세요:

1. mysqldump 사용:

mysqldump --user=root --password=XXX --single-transaction mydb > mydb.sql

2. MySQL Enterprise Backup 사용:

mysqlbackup --user=root --password=XXX --backup-dir=/backup backup-and-apply-log

3. Percona XtraBackup 사용:

xtrabackup --user=root --password=XXX --backup --target-dir=/backup/full

4. mydumper 사용 (멀티스레드):

mydumper --user=root --password=XXX --outputdir=/backup/mydb --threads=4

9. 성능 최적화

백업 속도 향상

1. --method 옵션으로 복사 방법 변경:

# 기본 cp 대신 rsync 사용
mysqlhotcopy --password=XXX --method=rsync mydb /backup/mysql/

2. 네트워크 백업 시 압축:

# scp로 원격 백업 시 압축
mysqlhotcopy --password=XXX --method="scp -C" mydb /backup/mysql/

3. 백업 후 압축:

# 백업 후 즉시 압축
mysqlhotcopy --password=XXX mydb /backup/mysql/ && \
    tar -czf /backup/mysql/mydb-$(date +%Y%m%d).tar.gz -C /backup/mysql mydb && \
    rm -rf /backup/mysql/mydb

시스템 부하 감소

ionice 사용 (I/O 우선순위 낮춤):

ionice -c3 mysqlhotcopy --password=XXX mydb /backup/mysql/

nice 사용 (CPU 우선순위 낮춤):

nice -n 19 mysqlhotcopy --password=XXX mydb /backup/mysql/

10. 모범 사례

백업 전략

1. 정기 전체 백업:

  • 매일 또는 매주 전체 백업 수행
  • 여러 세대 보관 (7일, 30일, 90일 등)

2. 증분 백업:

  • --addtodest 옵션으로 하루 중 여러 번 증분 백업
  • 스토리지 절약 및 복구 시간 단축

3. 원격 백업:

  • 로컬 백업 후 rsync로 원격 서버에 전송
  • 재해 복구 대비

백업 스크립트 예:

#!/bin/bash
# 전체 백업 + 원격 전송

# 로컬 백업
mysqlhotcopy --password=XXX --flushlog mydb /backup/mysql/

# 압축
tar -czf /backup/mysql/mydb-$(date +%Y%m%d).tar.gz -C /backup/mysql mydb

# 원격 전송
rsync -avz /backup/mysql/mydb-$(date +%Y%m%d).tar.gz \
    backup-server:/remote/backup/mysql/

# 로컬 임시 파일 삭제
rm -rf /backup/mysql/mydb

복원 테스트

정기적으로 복원 테스트 수행:

# 테스트 서버에서 복원
mysql -e "CREATE DATABASE test_restore"
service mysqld stop
cp -r /backup/mysql/mydb /var/lib/mysql/test_restore
chown -R mysql:mysql /var/lib/mysql/test_restore
service mysqld start
mysql -e "USE test_restore; SHOW TABLES;"

11. 대안 도구

mysqldump

장점:

  • 모든 스토리지 엔진 지원 (InnoDB, MyISAM 등)
  • 버전 간 호환성 우수
  • SQL 형식으로 복원 간편

사용 예:

mysqldump --user=root --password=XXX --single-transaction --routines --triggers mydb > mydb.sql

Percona XtraBackup

장점:

  • InnoDB hot backup 지원
  • 압축 및 암호화 기능
  • 증분 백업 지원

사용 예:

xtrabackup --user=root --password=XXX --backup --target-dir=/backup/full

mydumper

장점:

  • 멀티스레드로 빠른 백업
  • 테이블별 파일 분리
  • 압축 옵션 제공

사용 예:

mydumper --user=root --password=XXX --outputdir=/backup/mydb --threads=4 --compress

참고사항

  • mysqlhotcopy는 MyISAM 엔진 전용이므로 InnoDB 사용 시 mysqldump나 XtraBackup을 사용하세요.
  • MySQL 5.7 이후 버전에서는 deprecated 되었으므로 공식 도구 사용을 권장합니다.
  • 백업 중 테이블에 READ LOCK이 걸리므로 쓰기 작업이 차단됩니다.
  • 반드시 정기적인 복원 테스트를 수행하여 백업 유효성을 확인하세요.
  • 파일 시스템 레벨 복사이므로 동일한 MySQL 버전에서만 복원 가능합니다.
  • 백업 파일은 암호화권한 설정(chmod 600)을 철저히 하세요.
  • 원격 백업 및 여러 세대 보관으로 재해 복구 대비를 철저히 하세요.