57テーブルで〜2GBのInnoDBデータベースを使用するsymfonyアプリケーションがあります。データベースのサイズの大部分は、単一のテーブル(約1.2GB)にあります。現在、mysqldumpを使用してデータベースを毎晩バックアップしています。
コムキャスト接続のため、ダンプを手動で実行している場合、ダンプが完了する前にサーバーへの接続がタイムアウトして、ダンプを再実行する必要があることがよくあります。 [私は現在、毎晩ダンプを行うcronを実行しています。これは、手動で実行するダンプのためだけです。]
接続タイムアウトの問題のダンプを高速化する方法はありますが、サーバーがこのプロセスで占有されている時間を制限する方法もありますか?
ところで、私は現在、この問題を解決するためにデータベース全体のサイズを減らすことに取り組んでいます。
このようなダンプの主なボトルネックは、ドライブI/Oです。大量のデータを読み取り、再度書き込みます。いくつかの方法でこれをスピードアップできます:
gzip
などを介して出力をパイプ処理します。これは、実行される書き込みの量を減らします(そのため、全体のIO負荷とヘッドの移動量を減らします)が、CPU時間(ただし、これらの時間はとにかく)。--quick
オプションは、RAM大きなテーブルのバックアップによる影響)を低減します。ただし、間違った問題を修正している可能性があります。代わりに、接続のドロップに対処する方が簡単な場合があります(ただし、バックアップによるI/O負荷を減らすと、他のユーザーへの影響を減らすのに役立つため、とにかく試す価値があります)。 screen (または tmux のような同様のツール)を使用して手動バックアップを実行できますか?こうすることで、サーバーへの接続が切断された場合でも、プロセスが中断されることなく、screen
セッションに再接続して再接続できます。
接続を介してデータを直接送信する場合(つまり、ローカルマシンでリモートデータベースに対してmysqldumpを実行しているため、ダンプがローカルに表示される場合)、まずサーバーでダンプを実行し、必要に応じて圧縮してから転送することをお勧めします部分的な転送をサポートするツール(rsync
など)を使用したネットワーク経由のデータ。これにより、接続の切断によって中断された場合に、(再起動する代わりに)転送を再開できます。
「この問題を解決するためにデータベース全体のサイズを削減する」の一環として、データの大きなチャンクは変更されないと思います。 1.2Gbの大きなチャンクをそのメインテーブルから別のチャンクに移動して、mysqldump
呼び出しによってコピーされたチャンクから削除することができる場合があります。変更されない場合は、毎回このデータをバックアップする必要はありません。この方法でテーブルとデータベース間でデータを分割することは、通常、データパーティション化と呼ばれ、データとI/O負荷を複数のドライブに分散させることもできます。ハイエンドデータベースには自動パーティション分割のサポートが組み込まれていますが、mysqlではおそらく手動でそれを実行し、それを考慮してデータアクセス層を変更する必要があります。
このサイトのトピックから外れています(したがって、詳細が必要かどうかを確認するには、おそらくServerFaultまたはSuperUserにニップする必要があります):非アクティブのために接続が失われているように見える場合は、SSHサーバーとSSHクライアントのオプションを確認して、キープアライブパケットが有効になっていて、十分な頻度で送信されていることを確認してください。接続がアクティブでもドロップが表示される場合は、OpenVPNなどを使用して接続をラップすることもできます。接続全体が数秒間ダウンしている場合、SSHクライアントとサーバーは気づかない。
mysqldumpでバックアップを実行するための洞察
IMHOバックアップを行う方法がわかっている場合、バックアップを行うことはアートの形になっています
オプションがあります
オプション1:mysqldumpでmysqlインスタンス全体を
これは最も簡単な方法です。
mysqldump -h... -u... -p... --hex-blob --routines --triggers --all-databases | gzip > MySQLData.sql.gz
1つのファイルに書き込まれたすべて:テーブル構造、インデックス、トリガー、ストアドプロシージャ、ユーザー、暗号化されたパスワード。他のmysqldumpオプションは、さまざまなスタイルのINSERTコマンド、バイナリログからのログファイルと位置の座標、データベース作成オプション、部分データ(--whereオプション)などもエクスポートできます。
オプション2:mysqldumpの個別のデータベースを個別のデータファイルに
データベースのリストを作成することから始めます(これを行う2つの手法)
テクニック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が最も確実で安全です。手法2の方が優れているのは、ユーザーが/ var/lib/mysql(datadir)に汎用目的のフォルダーを作成し、データベースに関連しない場合があるためです。 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だけがすべてをもたらします。欠点は、この方法で作成されたmysqldumpは、mysqldumpが生成されたのと同じmajotリリースバージョンの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 &
注意すべきもう1つの点は、InnoDBに関するものです。 InnoDBバッファープールが大きい場合は、バックアップを実行する前にできる限りフラッシュするのが理にかなっています。そうでない場合、MySQLは、ダーティページが残っているテーブルをバッファプールからフラッシュする時間を費やします。これが私が提案するものです:
バックアップを実行する約1時間前に、このSQLコマンドを実行します
SET GLOBAL innodb_max_dirty_pages_pct = 0;
MySQL 5.5では、デフォルトのinnodb_max_dirty_pages_pctは75です。MySQL5.1以降では、デフォルトのinnodb_max_dirty_pages_pctは90です。innodb_max_dirty_pages_pctを0に設定することにより、ダーティページのディスクへのフラッシュを早めます。これにより、InnoDBテーブルに対してmysqldumpを実行する前に、InnoDBデータの不完全な2フェーズコミットをクリーンアップする影響が防止または少なくとも軽減されます。
mysqldumpの最後の単語
ほとんどの人はmysqldumpを避けて他のツールを支持しており、それらのツールは確かに優れています。
このようなツールには、
真のMySQL DBAの精神を持っている場合は、mysqldumpを採用して、それを完全に習得できます。すべてのバックアップが、MySQL DBAとしてのスキルを反映している可能性があります。
MySQLレプリケーションマスターからスレーブへの移行をご覧ください。マスターのデータベースを同じデータベースを持つ別のデータベースサーバーに複製できます。これには、マスターIDとスレーブIDが含まれます。スレーブは、マスターデータベースサーバーまたはそのデータベースの正確なコピーを作成します。マスターとスレーブの間には、1対1、多対多の関係がある場合があります。
スレーブは継続的にマスターでバイナリログを読み取り(バイナリログはマスターデータベースサーバーで書き込まれたクエリを保存します)、スレーブデータベースサーバーへの入力を取得します。 (つまり、マスターデータベースはまったく影響を受けません)
良いニュースは、ダウンタイムや遅いクエリ応答に気付かないため、MySQLサーバーにあまり影響を与えないことです。 10Gbのデータベースに使用しており、ダウンタイムなしで魅力的に機能します。
プランA:PerconaのXtrabackupも参照してください。これにより、大幅なロックなしでInnoDBのオンラインバックアップが可能になります。
プランB:スレーブを停止でき、いくつかの方法(ファイルのコピー、mysqldump、xtrabackupなど)のいずれかで一貫したバックアップをとることができます
プランC:LVMスナップショット。不可解な設定の後、データベースのサイズに関係なく、バックアップのダウンタイムは1分未満です。 mysqldを停止し、スナップショットを作成し、mysqldを再起動してから、スナップショットをコピーします。最後のステップには時間がかかることがありますが、MySQLはダウンしていません。
プランD:スレーブのスナップショット-ダウンタイムなし。
最初にいくつかの管理ポイント:ftpを実行するために接続していますか、それともsshを実行していて、それは死にかけていますか? sshの場合は、必ずscreenを使用して、comcastのクラッシュ後に再開できるようにしてください。 ftpの場合は、送信前にそれを圧縮していることを確認してください。
--optパラメータまたは--quickも試してください
--optこのオプションは、ダンプとリロードの操作をより効率的にするための一連の追加オプションをオンにします。具体的には、-add-drop-table、-add-locks、-all、-quick、-extended-insert、-lock-tables、および--disable-keysオプションを一緒に使用することと同等です。このオプションを使用すると、出力の移植性が低下し、他のデータベースシステムで理解されにくくなります。
--quickこのオプションは、サーバーから各行を読み取るときにダンプ出力を書き込むようにmysqldumpに指示します。これは、大きなテーブルに役立つ場合があります。デフォルトでは、mysqldumpは出力を書き込む前にテーブルからメモリにすべての行を読み取ります。大きなテーブルの場合、これには大量のメモリが必要になるため、ダンプが失敗する可能性があります。
大きなデータベースのダンプ中のタイムアウトにも問題がありました。最終的に解決したのは、db内のすべてのテーブルに個別のコマンドを送信し、次のように1つのファイルにすべてを追加することです。
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
別のバックアップソリューションではなく、mysqldumpで作成されたダンプファイルからより速く復元する方法についての問題だと思います。
これを行う方法の1つは、スキーマにテーブルのグループを作成し、グループごとに個別のDBユーザーを作成し、最後にMySQL権限を使用して、1人を除くすべてのDBユーザーを使用してテーブルを挿入できないようにすることです。
これは、実証済みの高速でほぼ並列の手法ですが、100%確実ではありません。500Gなどの大規模なダンプから復元するのにどのくらいの時間がかかりますか。しかし、私の控えめな意見では、あなたは何か平行するものが必要です。例については、以下のリンクをチェックしてください。
[MySQLのSQLダンプ(mysqldump)からの高速並列復元] [1]
「MySQLのSQLダンプ(mysqldump)からの高速な並列復元」