データの安全性に関しては、バックアップが非常に重要です。これらは究極のディザスタリカバリソリューションです。到達可能なデータベースノードがなく、データセンターが文字通り煙に包まれている可能性がありますが、データのバックアップがあれば、そのような状況から復旧できます。
通常、バックアップを使用して、さまざまなタイプのケースから回復します。
- WHERE句がない、または十分に具体的でないWHERE句がある偶発的なDROPTABLEまたはDELETE。
- データベースのアップグレードが失敗し、データが破損する
- ストレージメディアの障害/破損
バックアップからの復元だけでは不十分ですか?ポイントインタイムである必要がありますか?バックアップは、特定の時点で取得されたデータのスナップショットであることに注意する必要があります。午前1時にバックアップを取り、午前11時に誤ってテーブルが削除された場合、午前1時までデータを復元できますが、午前1時から午前11時の間に発生した変更についてはどうでしょうか。その間に発生した変更を再生できない限り、これらの変更は失われます。幸いなことに、MySQLには変更を保存するためのそのようなメカニズム(バイナリログ)があります。これらのログがレプリケーションに使用されていることをご存知かもしれません。MySQLはそれらを使用してマスターで発生したすべての変更を保存し、スレーブはそれらを使用してそれらの変更を再生し、データセットに適用します。 binlogにはすべての変更が保存されるため、それらを使用してトラフィックを再生することもできます。このブログ投稿では、ClusterControlがポイントインタイムリカバリ(PITR)の実行にどのように役立つかを見ていきます。
ポイントインタイムリカバリと互換性のあるバックアップの作成
まず、前提条件についてお話ししましょう。バックアップを作成するホストでは、バイナリログを有効にする必要があります。それらがなければ、PITRは不可能です。 2番目の要件-バックアップを取得するホストには、特定の時点に復元するために必要なすべてのバイナリログが必要です。あまりにも積極的なバイナリログローテーションを使用すると、これが問題になる可能性があります。
それでは、ClusterControlでこの機能を使用する方法を見てみましょう。まず、PITRと互換性のあるバックアップを取る必要があります。このようなバックアップは、完全で、完全で、一貫している必要があります。エクストラバックアップの場合、完全なデータセットが含まれている限り(スキーマのサブセットのみを含めていない場合)、PITRと互換性があります。
mysqldumpの場合、PITR互換にするオプションがあります。このオプションを有効にすると、必要なすべてのオプションが構成され(たとえば、ダンプに含める個別のスキーマを選択できなくなります)、バックアップはポイントインタイムリカバリに使用可能としてマークされます。
>バックアップからのポイントインタイムリカバリ
まず、復元するバックアップを選択する必要があります。
バックアップがPITRと互換性がある場合、ポイントインタイムリカバリを実行するためのオプションが表示されます。そのための2つのオプションがあります-「時間ベース」と「位置ベース」。これら2つのオプションの違いについて説明しましょう。
「時間ベースの」PITR
このオプションを使用すると、バックアップを復元する必要がある日時を渡すことができます。 1秒以内に定義できます。時間を定義するのが非常に正確であっても、1秒間に複数のイベントがバイナリログに記録される可能性があるため、すべてのデータが復元されることを保証するものではありません。データ損失が4月18日の10:00:01に発生したことを知っているとします。次の日時をフォームに渡します:「2018-04-1810:00:00」。バックアップが作成されたデータベースサーバーのタイムゾーン設定に基づく時間を使用する必要があることに注意してください。
データの損失が10:00:01に発生した最初のデータではない場合でも、その過程で一部のイベントが失われる可能性があります。それが何を意味するのか見てみましょう。
1秒間に、複数のイベントがbinlogに記録される場合があります。そのような場合を考えてみましょう:
10:00:00-イベントA、B、C、D、E、F
10:00:01-イベントV、W、X、Y、Z
ここで、Xはデータ損失イベントです。 1秒の粒度で、10:00:00(Fまで)または10:00:01(Zまで)に発生したすべてのものに復元できます。 Xが再実行されるため、後者の場合は役に立ちません。前者の場合、VとWが欠落しています。
そのため、位置ベースの復元がより正確になります。 「Wまで復元したい」と言えます。
時間ベースの復元は、バイナリログに移動して、復元する場所の正確な位置を定義しなくても取得できる最も正確なものです。これは、PITRを実行する2番目の方法につながります。
「位置ベース」PITR
ここでは、MySQLのコマンドラインツール、つまりmysqlbinlogユーティリティの経験が必要です。一方、リカバリの実行方法を最適に制御できます。
簡単な例を見てみましょう。上のスクリーンショットでわかるように、バックアップを復元するポイントまでのバイナリログ名とバイナリログ位置を渡す必要があります。ほとんどの場合、これはデータ損失イベントの前の最後の位置である必要があります。
誰かがSQLコマンドを実行した結果、重大なデータ損失が発生しました:
mysql> DROP TABLE sbtest1;
Query OK, 0 rows affected (0.02 sec)
私たちのアプリケーションはすぐに文句を言い始めました:
sysbench 1.1.0-ecf1191 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 2
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
FATAL: mysql_drv_query() returned error 1146 (Table 'sbtest.sbtest1' doesn't exist) for query 'DELETE FROM sbtest1 WHERE id=5038'
FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:490: SQL error, errno = 1146, state = '42S02': Table 'sbtest.sbtest1' doesn't exist
バックアップがありますが、その致命的な瞬間までのすべてのデータを復元したいと考えています。まず、アプリケーションが機能しないと想定しているため、DROPTABLEの後に発生したすべての書き込みを重要ではないものとして破棄できます。アプリケーションがある程度機能する場合は、後で残りの変更をマージする必要があります。では、バイナリログを調べて、DROPTABLEステートメントの位置を見つけましょう。すべてのバイナリログの解析を避けたいので、最新のバックアップがカバーした位置を見つけましょう。最新のバックアップセットのログを調べて、次のような行を探すことで確認できます。
したがって、ファイル名「binlog.000008」と位置「16184120」について話します。これを出発点として使用しましょう。持っているバイナリログファイルを確認しましょう:
[email protected]:~# ls -alh /var/lib/mysql/binlog.*
-rw-r----- 1 mysql mysql 58M Apr 17 08:31 /var/lib/mysql/binlog.000001
-rw-r----- 1 mysql mysql 116M Apr 17 08:59 /var/lib/mysql/binlog.000002
-rw-r----- 1 mysql mysql 379M Apr 17 09:30 /var/lib/mysql/binlog.000003
-rw-r----- 1 mysql mysql 344M Apr 17 10:54 /var/lib/mysql/binlog.000004
-rw-r----- 1 mysql mysql 892K Apr 17 10:56 /var/lib/mysql/binlog.000005
-rw-r----- 1 mysql mysql 74M Apr 17 11:03 /var/lib/mysql/binlog.000006
-rw-r----- 1 mysql mysql 5.2M Apr 17 11:06 /var/lib/mysql/binlog.000007
-rw-r----- 1 mysql mysql 21M Apr 18 11:35 /var/lib/mysql/binlog.000008
-rw-r----- 1 mysql mysql 59K Apr 18 11:35 /var/lib/mysql/binlog.000009
-rw-r----- 1 mysql mysql 144 Apr 18 11:35 /var/lib/mysql/binlog.index
したがって、「binlog.000008」に加えて、「binlog.000009」も調べる必要があります。バックアップログで見つかった位置から開始して、バイナリログをSQL形式に変換するコマンドを実行してみましょう。
[email protected]:~# mysqlbinlog --start-position='16184120' --verbose /var/lib/mysql/binlog.000008 /var/lib/mysql/binlog.000009 > binlog.out
行ベースのイベントをデコードするには、ノード「--verbose」が必要です。これは、探しているDROP TABLEには必ずしも必要ではありませんが、他のタイプのイベントには必要になる場合があります。
出力を検索してDROPTABLEクエリを探しましょう:
[email protected]:~# grep -B 7 -A 1 "DROP TABLE" binlog.out
# at 20885489
#180418 11:24:32 server id 1 end_log_pos 20885554 CRC32 0xb89f2e66 GTID last_committed=38168 sequence_number=38170 rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
# at 20885554
#180418 11:24:32 server id 1 end_log_pos 20885678 CRC32 0xb38a427b Query thread_id=54 exec_time=0 error_code=0
use `sbtest`/*!*/;
SET TIMESTAMP=1524050672/*!*/;
DROP TABLE `sbtest1` /* generated by server */
/*!*/;
このサンプルでは、2つのイベントを確認できます。まず、20885489の位置で、GTID_NEXT変数を設定します。
# at 20885489
#180418 11:24:32 server id 1 end_log_pos 20885554 CRC32 0xb89f2e66 GTID last_committed=38168 sequence_number=38170 rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
次に、20885554の位置にDROPTABLEイベントがあります。これにより、20885489の位置までPITRを実行する必要があるという結論に至ります。答える唯一の質問は、どのバイナリログについて話しているかです。 binlogローテーションエントリを検索することで確認できます:
[email protected]:~# grep "Rotate to binlog" binlog.out
#180418 11:35:46 server id 1 end_log_pos 21013114 CRC32 0x2772cc18 Rotate to binlog.000009 pos: 4
日付を比較するとはっきりとわかるように、binlog.000009へのローテーションは後で発生したため、binlog.000008をフォームのbinlogファイルとして渡します。
次に、クラスターでバックアップを復元するか、外部サーバーを使用して復元するかを決定する必要があります。この2番目のオプションは、データのサブセットのみを復元する場合に役立ちます。別のホストで完全な物理バックアップを復元してから、mysqldumpを使用して不足しているデータをダンプし、本番サーバーにロードすることができます。
クラスタでバックアップを復元するときは、復元したノード以外のノードを再構築する必要があることに注意してください。マスター/スレーブのシナリオでは、通常、マスターのバックアップを復元してから、マスターからスレーブを再構築する必要があります。
最後のステップとして、ClusterControlが実行するアクションの概要が表示されます。
最後に、バックアップが復元された後、欠落しているテーブルが復元されたかどうかをテストします。
mysql> show tables from sbtest like 'sbtest1'\G
*************************** 1. row ***************************
Tables_in_sbtest (sbtest1): sbtest1
1 row in set (0.00 sec)
すべて問題ないようです。不足しているデータを復元することができました。
私たちが取らなければならない最後のステップは、スレーブを再構築することです。 PITRバックアップを使用するオプションがあることに注意してください。この例では、スレーブがDROP TABLEイベントを複製し、マスターとの整合性が失われるため、これは不可能です。