ZFSスナップショットを介してMySQLデータベースをバックアップする


12

私はこれを正確に行うことについて話している多くのサイトを見つけましたが、いくつかの重要な詳細を見逃しています。一般的な手順は

  • 走る FLUSH TABLES WITH READ LOCK
  • ZFSスナップショットを撮る
  • 走る UNLOCK TABLES

さまざまな情報源は、私が使用しているInnoDBは実際にはを尊重しないと報告していFLUSHます。MySQLユーザーマニュアルFLUSH TABLES...FOR EXPORTには、InnoDBで使用するバリアントがありますが、データベース全体をバックアップするのではなく、各テーブルを個別に指定する必要があると記載されています。テーブルのリストが実際に存在するテーブルと同期しなくなる可能性があるため、各テーブルを個別に指定することは避けたいと思います。

私が抱えている他の問題は、私がのようなことをする予定であったことですmysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK"。ただし、これにより、セッションが終了した直後にロックが解除されます。これは理にかなっていますが、スナップショットを撮るときに読み取りロックを保持する必要があるため、かなり面倒です。

私の他のアイデアは、Percona XtraBackupのようなツールを使用してホットバックアップを作成し、バックアップのスナップショットを取得することですが、スナップショットを作成するためだけにすべてのデータを2番目の場所に書き込むコストを払わないことを望みます。


テーブルの静的リストがあるのはなぜですか?実行時に確実にリストを動的に生成できます。
EEAA

1
データベースはVM上ですか、それともベアメタル上ですか?ストレージは同じマシン上にありますか?
マイケルハンプトン

EEAA、かなり公平。
アンディシュルマン

Michael、データベースとZFSボックスは異なるマシンですが、どちらも仮想化されていません。
アンディシュルマン

@AndyShulmanレイアウトについてもう少し詳しく説明する必要があると思います。これは意味がありません。
ewwhite

回答:


4

すべてのテーブルにInnoDBのみを使用し、以下に設定innodb_flush_log_at_trx_commitする場合:

  • 1 (InnoDBログバッファーの内容は、トランザクションのコミットごとにログファイルに書き込まれ、ログファイルはディスクにフラッシュされます)または、
  • 2 (InnoDBログバッファーの内容は、各トランザクションのコミット後にログファイルに書き込まれ、ログファイルは1秒に1回程度ディスクにフラッシュされます)、

スナップショットを実行する前にFLUSH TABLESは必要ありません。ZFSスナップショットを直接実行するだけです。InnoDBは、データを失うことなく、トランザクションコミットログからデータを回復できます。

参照:https : //dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit


MySQL 8で導入されたデータディクショナリにより、DDL(スキーマ変更)操作でさえアトミックになりました。それ以前は、ファイルシステムのスナップショット中のDDL操作により、部分的にコミットされた(つまり破損した)結果が発生する可能性がありました。
バーニー

13

(ほとんどの)データベースを一貫してバックアップするには、完全なデータベースロックが必要です。

マニュアルhttps://dev.mysql.com/doc/refman/5.5/en/backup-methods.htmlには、ZFSスナップショットに特に適した読み取りロック付きのフラッシュテーブルが記載されています。

ファイルシステムスナップショットを使用したバックアップの作成

Veritasファイルシステムを使用している場合、次のようなバックアップを作成できます。

  1. クライアントプログラムからを実行しFLUSH TABLES WITH READ LOCKます。
  2. 別のシェルから、マウントvxfsスナップショットを実行します。
  3. 最初のクライアントから、を実行しUNLOCK TABLESます。
  4. スナップショットからファイルをコピーします。
  5. スナップショットをアンマウントします。

同様のスナップショット機能は、LVMやZFSなどの他のファイルシステムでも使用できます。

ばかげての一種である彼らはあなたが必要とするという事実に取り残さことFLUSH TABLES table_a, table_b, table_c FOR EXPORTのためのInnoDBの手順からを。また、そのような各テーブルを指定しなければならないのも愚かなことです。しかし、EEAAが言うように、バックアップを開始するときにかなり簡単にテーブルのリストを生成できます。

ロックを保持することに関しては、スナップショットの実行中にデータベース接続をアクティブに保つ必要があります

一般に、Perlや他のプログラミング言語のようなものを使用して、接続、dbのロック、db接続の維持中にスナップショットの取得、ロック解除および切断を行うことができます。複雑ではありません。既にこれを行うツールが存在することを望んでいますが、それを書くのは簡単です。

簡単なこと、複雑なことなどではありません。基本的なプログラミングまたは優れたスクリプト作成スキルがあることを前提としています。


このような概念的にシンプルなスクリプトをBashに保持したいと思っていましたが、言語を切り替えるとこれがはるかに簡単になります。私はあなたの答えを間違って読んかもしれないが、それはあなたが、私は両方を実行する必要が言っているに見えFLUSH TABLES WITH READ LOCK当時とFLUSH TABLES...FOR EXPORTMySQLのマニュアルの私の読書は一つだけが必要であるべきと言うのに対し、。
アンディシュルマン

すみません、はっきりしませんでした。私はちょうどマニュアルで行くとそれは2つの異なることを言っています。私はあなたが正しいと推測し、後者だけが必要です。ただし、1つのコマンドですべてのテーブルをロックする必要があります。
ライアンバチシン16

1
ドキュメントがあまり明確ではないため、データベース全体をロックする必要があり、スナップショットの作成中にDB接続を維持する必要があるため、DBをシャットダウン、バックアップ、再起動する方が簡単ですそれ。
アンドリューヘンレ

2
@アンドリューため息...わかりました。しかし、それは遅くなり、接続がドロップ/失敗する原因になり、データベースが適切にバックアップに失敗することがわかりました(自動化に悪い)。mysql / Oracleから最終的な回答を得ることは良いことです。メーリングリストが必要です。
ライアンバブチシン16

7

Tobiaによる別のServer Faultの投稿で見つけたBashの概念的にシンプルなスクリプトを取り込んで、適応させました。そこから約90%の道のりが得られるはずです。

mysql_locked=/var/run/mysql_locked

# flush & lock MySQL, touch mysql_locked, and wait until it is removed
mysql -hhost -uuser -ppassword -NB <<-EOF &
    flush tables with read lock;
    delimiter ;;
    system touch $mysql_locked
    system while test -e $mysql_locked; do sleep 1; done
    exit
EOF

# wait for the preceding command to touch mysql_locked
while ! test -e $mysql_locked; do sleep 1; done

# take a snapshot of the filesystem, while MySQL is being held locked
zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M")

# unlock MySQL
rm -f $mysql_locked

ここで、mysql使用するコマンドはバックグラウンドで実行され、ファイルに触れます。バックグラウンドでファイルが消えるのを待ってから終了し、テーブルのロックを解除します。一方、メインスクリプトはファイルが存在するまで待機し、スナップショットを作成してファイルを削除します。

によって指し示されるファイルは$mysql_locked両方のマシンからアクセス可能である必要がありますが、それらは両方とも共通のデータセットにアクセスできるため、十分に簡単に実行できるはずです(ただし、異なるパスを使用する可能性があり、これを考慮する必要があります)。


私はMySQLスクリプトを知らないので、これは馬鹿げたアイデアかもしれませんがsystem zfs snapshot...、メインスクリプト内だけではできませんか?またはスナップショット製造はない持っている別のプロセスで実行するように?
-TripeHound

@Tripehound両方のことを何らかの形で並行して行う必要があります
ライアンバブチシン

@RyanBabchishin彼は正しいと思う、実は。SYSTEMコマンドは、ローカルで物事を実行します。FreeBSDボックスでmysqlクライアントを実行して実行するとLOCK; SYSTEM zfs snapshot; UNLOCK、動作するようです。
アンディシュルマン

@アンディ私はちょうどそれらが並行して起こる必要があると言った。どのようにそれを進めても構いません。
ライアンバブチシン16

2

myisamには、ジャーナリングではないため、読み取りロック付きのフラッシュテーブルが必要です。

INOはジャーナリングであるため、実際にはinnodbには何も必要ありません。とにかく一貫性があり、スナップショットのアトミックな瞬間に何かが発生した場合にジャーナルを自動的にロールバックします。

アプリケーションレベルの一貫性が必要な場合は、アプリケーションでトランザクションを使用する必要があります。アプリケーションでトランザクションとinnodbを使用している場合、スナップショットはアプリケーションレベルまで自動的に一貫性が保たれます。


2

これは、ロックを保持しながらZFSスナップショットを作成する方法です。

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.