큰 데이터베이스의 mysqldump를 어떻게 최적화 할 수 있습니까?


173

57 테이블이 ~ 2GB 인 InnoDB 데이터베이스가있는 심포니 응용 프로그램이 있습니다. 데이터베이스 크기의 대부분은 단일 테이블 (~ 1.2GB)에 있습니다. 현재 데이터베이스를 야간에 백업하기 위해 mysqldump를 사용하고 있습니다.

comcast 연결로 인해 덤프를 수동으로 실행하는 경우 종종 덤프가 완료되기 전에 서버에 대한 연결이 시간 초과되어 덤프를 다시 실행해야합니다. [현재는 매일 밤 덤프를 수행하는 크론을 실행합니다. 이는 수동으로 실행하는 덤프에만 해당됩니다.]

연결 시간 초과 문제에 대한 덤프 속도를 높이고 서버가이 프로세스에 사용되는 시간을 제한하는 방법이 있습니까?

BTW, 나는 현재이 문제를 해결하기 위해 전체 데이터베이스의 크기를 줄이기 위해 노력하고 있습니다.


2
mysqldump 명령으로 전달할 매개 변수는 무엇입니까?
Toby

--compact를 추가하는 것이 옵션 일 수 있습니다.
Toby

정말 아무것도 –mysqldump [database] -u[user] -p'[password]' > db_backup.sql
Patrick

4
screen상황 에 대한 간단한 대안 은을 사용 nohup하는 것입니다. 연결이 끊어 지더라도 서버에서 명령을 계속 실행할 수 있습니다. 예 nohup mysqldump [options] > backup.sql 2> backup.err &. 에 대한 출력 파일을 제공하지 않으면 기본적으로 nohup생성 nohup.out됩니다.
dabest1

1
(A)에서 찾아 보게 at하고 screen(설치 한 경우 후자를하지만, at모든 유닉스에 대한 표준) 또는 ServerAliveInterval너무 오래 유휴 연결 후 종료, 방화벽을 다루는 방법에 대한 SSH에 대한 옵션을 제공합니다.
MattBianco

답변:


134

이와 같은 덤프의 주요 병목 현상은 드라이브 I / O입니다. 많은 양의 데이터를 읽고 다시 쓰고 있습니다. 여러 가지 방법으로 속도를 높일 수 있습니다.

  • 출력이 데이터베이스 파일이 저장된 것과 다른 드라이브로 가고 있는지 확인하십시오-드라이브 헤드가 읽는 위치 사이에서 지속적으로 깜박이지 않기 때문에 디스크 회전과 큰 차이가 있습니다. 그리고 작성되는 위치.
  • mysqldump의 출력은 매우 압축 가능하므로 위에서 언급 한대로 출력을 입력과 분리 할 수없는 경우 출력을 파이프로 gzip또는 이와 유사하게 파이프하십시오 . 이렇게하면 CPU 시간 (어쨌든이 시간에 많은 여유가있을 수 있음)을 희생시키면서 쓰기 양이 줄어들고 (전체 IO로드와 헤드 이동량이 줄어 듭니다).
  • 또한 (압축 대신 또는 압축 대신) 큰 쓰기 버퍼를 지원 하는 파이프 유틸리티 ( pv 와 같은 )를 통해 출력을 전달 하여 드라이브에 쓰여진 블록을 더 그룹화하여 헤드 이동 대기 시간의 영향을 다시 줄입니다. --quick옵션을 사용하여 큰 테이블을 백업 할 때의 RAM 영향을 줄이면 상당한 차이가 있습니다).
  • IO로드가 낮은 경우에만 백업 프로세스를 실행하십시오.

잘못된 문제를 해결할 수도 있습니다. 대신 연결 끊김 문제를 해결하는 것이 더 쉬울 수 있습니다 (백업에 의해 부과되는 I / O로드를 줄이면 다른 사용자에게 미치는 영향을 줄이는 데 도움이 될 수 있습니다). 화면 (또는 tmux 와 같은 유사한 도구)을 통해 수동 백업을 실행할 수 있습니까? 이렇게하면 서버와의 연결 screen이 끊어 지면 프로세스를 중단하지 않고 세션에 다시 연결하고 다시 연결할 수 있습니다 .

연결을 통해 직접 데이터를 전송하는 경우 (즉, 원격 데이터베이스에 대해 로컬 컴퓨터에서 mysqldump를 실행하여 덤프가 로컬로 표시되는 경우) 먼저 서버에서 덤프를 실행하고 필요에 따라 압축 한 다음 전송하는 것이 좋습니다. rsync부분 전송을 지원 하는 도구 (예 : 등 )를 사용하여 네트워크를 통해 데이터를 연결하면 연결 끊기가 중단 된 경우 다시 시작하는 대신 전송을 다시 시작할 수 있습니다.

"이 문제를 해결하기 위해 전체 데이터베이스의 크기를 줄이는 것"의 일부로 많은 양의 데이터가 변경되지 않는다고 생각합니다. 1.2Gb의 큰 청크를 해당 기본 테이블에서 다른 테이블로 옮기고 mysqldump호출에 의해 복사 된 청크에서 제거 할 수 있습니다 . 이 데이터가 절대 변경되지 않으면 매번 백업 할 필요는 없습니다. 이러한 방식으로 테이블과 데이터베이스간에 데이터를 분할하는 것을 일반적으로 데이터 분할이라고하며 여러 드라이브에 데이터 및 I / O로드를 분산시킬 수도 있습니다. 고급 데이터베이스는 자동 파티셔닝을 기본적으로 지원하지만 mysql에서는 데이터베이스를 수동으로 수행하고이를 고려하여 데이터 액세스 계층을 변경해야 할 것입니다.

이 사이트에 대한 주제를 벗어남 (따라서 ServerFault 또는 SuperUser를 통해 자세한 정보가 필요한지 물어볼 수 있습니다) : 비활성으로 인해 연결이 끊어 질 경우 SSH 서버 및 SSH 클라이언트의 옵션을 확인하십시오. 연결 유지 패킷이 활성화되어 있고 자주 전송되고 있는지 확인하십시오. 연결이 활성화되어 있어도 끊김 현상이 발생하면 OpenVPN 또는 이와 유사한 연결을 사용하여 연결을 감쌀 수도 있습니다. SSH 클라이언트 및 서버는 알지 못합니다.


서버로의 ssh 연결 끊김 수를 줄일 수 있기를 바랍니다. ~ 60 초 이상 터미널을 사용하지 않을 것으로 예상 top되면 연결이 끊어지지 않도록 실행 합니다. (우리는 직장에서 표준 WRT 라우터 및 방화벽 만 사용하고 내 홈 캐스트 연결이 끊어지지 않기 때문에 그것이 캐스트 연결이라고 확신합니다)
Patrick

SSH 연결과 관련된 간단한 메모를 추가했습니다.
David Spillett

2
이 답변에 대한 깊이와 통찰력. 이를 위해 +3을 받아야합니다. 죄송합니다. +1 만 줄 수 있습니다.
RolandoMySQLDBA 2016 년

116

mysqldump를 이용한 백업에 대한 통찰력

IMHO 백업을 수행하는 방법을 알고 있다면 백업을하는 것이 예술적인 형태가되었습니다.

당신은 옵션이 있습니다

옵션 1 : mysqldump 전체 mysql 인스턴스

이것은 가장 쉬운 방법입니다.

mysqldump -h... -u... -p... --hex-blob --routines --triggers --all-databases | gzip > MySQLData.sql.gz

하나의 파일로 작성된 모든 것 : 테이블 구조, 인덱스, 트리거, 저장 프로 시저, 사용자, 암호화 된 비밀번호. 다른 mysqldump 옵션은 다른 스타일의 INSERT 명령, 로그 파일 및 이진 로그에서 로그 위치 및 좌표, 데이터베이스 생성 옵션, 부분 데이터 (--where 옵션) 등을 내보낼 수 있습니다.

옵션 2 : mysqldump 별도의 데이터베이스를 별도의 데이터 파일로 분리

데이터베이스 목록을 작성하여 시작하십시오 (이를 수행하는 두 가지 기술).

기술 1

mysql -h... -u... -p... -A --skip-column-names -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

기술 2

mysql -h... -u... -p... -A --skip-column-names -e"SELECT DISTINCT table_schema FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

기술 1이 가장 빠른 방법입니다. 기술 2가 가장 안전하고 안전합니다. 때로는 사용자가 데이터베이스와 관련이없는 / var / lib / mysql (datadir)에 일반 용도로 폴더를 작성하기 때문에 기술 2가 더 좋습니다. information_schema는 폴더를 information_schema.schemata 테이블에 데이터베이스로 등록합니다. 기술 2는 mysql 데이터가없는 폴더를 우회합니다.

일단 데이터베이스 목록을 컴파일하면 원하는 경우 병렬로 목록을 반복하여 mysqldump 할 수 있습니다.

for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
done
wait

한 번에 시작할 데이터베이스가 너무 많은 경우 한 번에 10 개씩 병렬 덤프하십시오.

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

옵션 3 : mysqldump를 별도의 데이터 파일로 분리

테이블 목록을 작성하여 시작

mysql -h... -u... -p... -A --skip-column-names -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfTables.txt

그런 다음 10 개의 그룹으로 모든 테이블을 덤프하십시오.

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DBTB in `cat ListOfTables.txt`
do
    DB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $2}'`
    mysqldump -h... -u... -p... --hex-blob --triggers ${DB} ${TB} | gzip > ${DB}_${TB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

옵션 4 : 이미지 사용

위에서 언급 한 옵션과 깔끔한 ​​스냅 샷 기술의 변형을 시도하십시오

  1. 각 테이블의 크기를 오름차순 또는 내림차순으로 테이블 목록을 정렬하십시오.
  2. 별도의 프로세스를 사용하여 mysqldump를 시작하기 전에 "읽기 잠금이있는 FLUSH 테이블; SELECT SLEEP (86400)"을 실행하십시오. mysqldumps가 완료된 후이 프로세스를 종료하십시오. 데이터베이스에 InnoDB와 MyISAM이 모두 포함 된 경우에 유용합니다
  3. mysqldump를 날짜가 지정된 폴더에 저장하고 이전 백업 폴더를 회전시킵니다.
  4. 전체 인스턴스 mysqldump를 독립형 서버에로드하십시오.

경고

옵션 1 만 모든 것을 제공합니다. 단점은 이런 방식으로 생성 된 mysqldump가 mysqldump가 생성 된 것과 동일한 majot release 버전의 mysql로만 다시로드 될 수 있다는 것입니다. 즉, MySQL 5.0 데이터베이스의 mysqldump는 5.1 또는 5.5로로드 할 수 없습니다. 이유 ? mysql 스키마는 주요 릴리스마다 완전히 다릅니다.

옵션 2와 3에는 사용자 이름과 비밀번호 저장이 포함되지 않습니다.

읽기 쉽고 이식 가능한 사용자를 위해 SQL Grants를 덤프하는 일반적인 방법은 다음과 같습니다.

mysql -h... -u... -p... --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql -h... -u... -p... --skip-column-names -A | sed 's/$/;/g' > MySQLGrants.sql

옵션 3은 저장 프로 시저를 저장하지 않으므로 다음을 수행 할 수 있습니다.

mysqldump -h... -u... -p... --no-data --no-create-info --routines > MySQLStoredProcedures.sql &

주목해야 할 또 다른 사항은 InnoDB에 관한 것입니다. 큰 InnoDB 버퍼 풀이있는 경우 백업을 수행하기 전에 최대한 플러시하는 것이 좋습니다. 그렇지 않으면 MySQL은 남아있는 더티 페이지가 버퍼 풀에서 테이블을 플러시하는 데 시간을 보냅니다. 여기 내가 제안하는 것이 있습니다.

백업을 수행하기 약 1 시간 전에이 SQL 명령을 실행하십시오.

SET GLOBAL innodb_max_dirty_pages_pct = 0;

MySQL 5.5에서 기본 innodb_max_dirty_pages_pct는 75입니다. MySQL 5.1 이상에서 기본 innodb_max_dirty_pages_pct는 90입니다. innodb_max_dirty_pages_pct를 0으로 설정하면 더티 페이지를 디스크로 플러시하는 것이 빨라집니다. 이렇게하면 InnoDB 테이블에 대해 mysqldump를 수행하기 전에 InnoDB 데이터의 불완전한 2 단계 커밋을 정리하는 영향을 방지하거나 최소한 줄일 수 있습니다.

mysqldump의 최종 단어

대부분의 사람들은 다른 도구를 선호하기 때문에 mysqldump를 피하고 그 도구는 실제로 좋습니다.

이러한 도구에는 다음이 포함됩니다

  1. MAATKIT ( Percona의 병렬 덤프 / 복원 스크립트 [사용되지 않지만 훌륭함 ])
  2. XtraBackup (Percona의 TopNotch 스냅 샷 백업)
  3. CDP R1Soft ( 특정 스냅 샷을 작성하는 MySQL 모듈 옵션 )
  4. MySQL Enterprise Backup (이전의 InnoDB Hot Backups [상업용])

진정한 MySQL DBA의 정신이 있다면, mysqldump를 수용하고이를 달성 할 수있는 완전한 숙달을 가질 수 있습니다. 모든 백업이 MySQL DBA로서의 기술을 반영하기를 바랍니다 .


2
mysqldump와 잘 사용하기 위해 +1 : 진정한 MySQL DBA의 정신이 있다면, mysqldump를 수용하고이를 달성 할 수있는 완전한 숙달을 가질 수 있습니다. 모든 백업이 MySQL DBA로서의 기술을 반영하기를 바랍니다.
Abdul Manaf

4
InnoDB에서 테이블을 개별적으로 덤프하면 일관성없는 백업이 제공됩니다.
Alain Collins

5
@AlainCollins 이것이 바로 읽기 전용 인 복제 슬레이브에서 mysqldumps를 실행하는 이유입니다. Seconds_Behind_Master가 0이면 STOP SLAVE를 실행합니다. 이제 위에서 언급 한 스타일로 mysqldump를 수행 할 수있는 일관된 시점이 있습니다. 지난 5 년 동안 온라인 거래 회사에 대해 본인이나 회사 소유주에게 단일 불만을 제기하지 않고이를 수행했습니다. 현재이 클라이언트에 대해 10 분마다 병렬 mysqldump를 수행합니다. 또한 다른 클라이언트에서 더 빠른 백업 기간을 제공하기 위해이 작업을 수행합니다.
RolandoMySQLDBA

32GB db가 있으므로 옵션 3이 내가 염두에두고있는 것입니다! 감사!
Raymond

1TB의 데이터를 백업하고 다시 가져 와서 크게 축소해야 ibdata1합니다. 하드웨어 RAID가 지원하는 SSD 시대에는 옵션 3이 유일한 해결책입니다.
rabudde

18

MySQL 복제 마스터에서 슬레이브로 살펴보십시오. 마스터 데이터베이스를 동일한 데이터베이스가있는 다른 데이터베이스 서버로 복제 할 수 있습니다. 여기에는 마스터 및 슬레이브 ID가 포함됩니다. 슬레이브 자체는 마스터 데이터베이스 서버 및 / 또는 데이터베이스의 정확한 사본입니다. 마스터 (들)와 슬레이브 (들) 사이에는 일대일, 다 대일, 일대 다 관계가있을 수 있습니다.

슬레이브는 마스터에서 이진 로그를 지속적으로 읽고 (빈 로그는 마스터 데이터베이스 서버에 작성된 쿼리를 저장함) 슬레이브 데이터베이스 서버에 입력을받습니다. (이는 마스터 데이터베이스가 전혀 영향을받지 않음을 의미합니다)

좋은 소식은 다운 타임이나 쿼리 응답이 느려지지 않기 때문에 MySQL 서버에 큰 영향을 미치지 않는다는 것입니다. 우리는 10Gb 데이터베이스에 사용하며 다운 타임없이 매력처럼 작동합니다.

동일한 머신에서 MySQL 복제


그것이 저에게 효과적 일지 모르지만 약간 과잉 일 수도 있습니다. 응용 프로그램의 요구 사항이 변경 될 경우이를 염두에 두지 만 현재는 백업 수준이 필요하지 않습니다.
Patrick

4
복제본을 백업하여 주 DB에서 백업의 IO로드를 제거하고 잠재적 인 잠금 관련 문제를 줄이려면 +1입니다. 한 가지 중요한 경고가 있습니다. IO 대역폭을 위해 마스터와 경쟁 할 수 있습니다.이 문제를 완화하기 위해 슬레이브의 데이터 파일이 마스터와 다른 드라이브 / 배열인지 확인하십시오.
David Spillett

1
David Splllet의 의견에 대한 Ditto. My Web Hosting Employer의 슬레이브에 mysqldump 백업을 사용하여 수십 개의 마스터 / 슬레이브를 설정하고 유지 관리합니다. 나도 +1
RolandoMySQLDBA 2016 년

16

계획 A : Percona의 Xtrabackup도 참조하십시오. 이를 통해 중요한 잠금없이 InnoDB를 온라인으로 백업 할 수 있습니다.

계획 B : 슬레이브를 중지 할 수 있으며 여러 방법 (복사 파일, mysqldump, xtrabackup 등)으로 일관된 백업을 수행 할 수 있습니다.

계획 C : LVM 스냅 샷. 일부 암호화 설정 후 데이터베이스의 크기에 관계없이 백업 중단 시간은 1 분 미만입니다. mysqld를 중지하고 스냅 샷을 수행 한 다음 mysqld를 다시 시작한 다음 스냅 샷을 복사하십시오. 마지막 단계는 시간이 오래 걸리지 만 MySQL은 다운되지 않습니다.

계획 D : 슬레이브 스냅 샷-다운 타임 제로.


2
네 계획 모두 후라. 답변 당 +0.25 만 줄 수 있습니다 !!! +1 (4 x 0.25)
RolandoMySQLDBA

15

몇 가지 관리 포인트가 먼저 있습니다 : ftp를 수행하기 위해 연결 중입니까, 아니면 ssh'ed이고 죽어 가고 있습니까? ssh 인 경우 comcast 충돌 후 다시 시작할 수 있도록 screen 을 사용해야 합니다. ftp 인 경우 보내기 전에 압축 / 타르를 압축하고 있는지 확인하십시오.

--opt 매개 변수 또는 --quick

--opt이 옵션은 덤프 및 재로드 작업을보다 효율적으로 수행하기 위해 추가 옵션 세트를 켭니다. 특히 --add-drop-table, --add-locks, --all, --quick, --extended-insert, --lock-tables 및 --disable-keys 옵션을 함께 사용하는 것과 같습니다. 이 옵션은 다른 데이터베이스 시스템에서 출력을 쉽게 이식 할 수없고 이해하기 어렵게합니다.

--quick이 옵션은 mysqldump가 서버에서 각 행을 읽을 때 덤프 출력을 쓰도록 지시합니다. 이는 큰 테이블에 유용 할 수 있습니다. 기본적으로 mysqldump는 출력을 쓰기 전에 테이블의 모든 행을 메모리로 읽습니다. 큰 테이블의 경우 많은 양의 메모리가 필요하므로 덤프가 실패 할 수 있습니다.


1
--opt는 결과적으로 출력되는 파일 크기를 늘리지 않습니까?
Toby

그것은 그의 문제에 더 많은 해답을주는 --quick를 추가 할 예정입니다. 감사!
David Hall

이 문제를 완전히 피하는 화면 +1
Gaius

mysqldump의 --opt 및 --quick 설명에 대한 매우 훌륭하고 간결한 답변은 +1입니다.
RolandoMySQLDBA

1
--opt는 기본적으로 켜져 있습니다.
Jordan

5

큰 데이터베이스를 덤프하는 동안 시간 초과 문제가 발생했습니다. DB의 모든 테이블에 대해 개별 명령을 보내고 다음과 같이 하나의 파일에 모든 것을 추가하여 마침내 해결했습니다.

TABLES=`mysql -u $USER -p$PWD -Bse 'show tables' $DB`
for TABLE in $TABLES
do
    mysqldump -u $USER -p$PWD $DB $TABLE >> dump.sql
done

4
이는 "일관되지 않은"백업으로 간주됩니다. 복원시 한 테이블에 다른 테이블에 매핑되지만 존재하지 않는 데이터가있을 수 있습니다.
Morgan Tocker

3

문제는 다른 백업 솔루션이 아닌 mysqldump가 만든 덤프 파일에서 더 빠르게 복원하는 방법에 관한 것입니다.

방법 중 하나는 스키마에 테이블 그룹을 생성하고 각 그룹에 대해 별도의 DB 사용자를 만든 다음 MySQL 권한을 사용하여 한 명의 DB 사용자를 제외한 모든 사용자에게 테이블을 삽입 할 수 없도록하는 것입니다.

이것은 500G 정도의 큰 덤프에서 복원하는 데 시간이 얼마나 걸리는 것으로 입증 된 빠르고 거의 병렬 기술이지만 100 % 확실하지는 않습니다. 그러나 나의 겸손한 견해로는 비슷한 것이 필요합니다. 아래 링크를 확인하십시오.

[MySQL 용 SQL 덤프 (mysqldump)로부터의 빠른 병렬 복원] [1]

http://geeksww.com/tutorials/database_management_systems/mysql/tips_and_tricks/fast_parallel_restore_from_sql_dumps_mysqldump_for_mysql.php

"MySQL 용 SQL 덤프 (mysqldump)에서 빠르고 병렬로 복원"


2
이것은 다른 질문에 대한 귀하의 답변 의 정확한 사본입니다 . 이 특정 질문에 대해 조금 더 사용자 정의 할 수 있습니다.
Paul White

문제는 구체적으로 더 빠르게 복원하는 방법에 관한 것이 아닙니다.
Andrew Lorien
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.