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=username | MySQL 사용자명 | --user=root |
--password=pass | MySQL 비밀번호 | --password=secret |
--port=port | MySQL 포트 | --port=3306 |
--socket=path | Socket 파일 경로 | --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)을 철저히 하세요.
- 원격 백업 및 여러 세대 보관으로 재해 복구 대비를 철저히 하세요.