最後のセクション セクション7.5.1「バイナリログを使用したポイントインタイムリカバリ」 では、バイナリログを使用してポイントインタイムリカバリを実行する一般的な考え方について説明します。 このセクションでは、操作の詳細を例とともに説明します。
たとえば、2020 年 3 月 11 日の約 20:06:00 に、テーブルを削除する SQL ステートメントが実行されたとします。 point-in-time リカバリを実行して、テーブルの削除直前の状態にサーバーをリストアできます。 これを実現するためのサンプルステップを次に示します:
-
目的の時点より前に作成された最後の全体バックアップをリストアします (この例では 2020 年 3 月 11 日の 20:06:00 である
tp
と呼びます)。 終了したら、あとで使用するためにサーバーを復元したバイナリログの位置を書き留め、サーバーを再起動します。注記最後にリカバリされたバイナリログの位置は、リストアおよびサーバーの再起動後に InnoDB によっても表示されますが、表示された位置に反映された時間の後に DDL イベントおよび InnoDB 以外の変更が発生した可能性があるため、リストアの終了ログの位置を取得する信頼性のない方法です。 バックアップおよびリストアツールでは、リカバリ用の最後のバイナリログの位置を指定する必要があります: たとえば、タスクに mysqlbinlog を使用している場合は、バイナリログリプレイの停止位置を確認します。MySQL Enterprise Backup を使用している場合は、最後のバイナリログの位置がバックアップに保存されています。 Point-in-Time Recoveryを参照してください。
-
データベースをリストアする時点に対応する正確なバイナリログイベント位置を検索します。 この例では、テーブルの削除が行われたおよその時間 (
tp
) がわかっている場合、mysqlbinlog ユーティリティを使用してその時間の前後のログコンテンツを確認することで、ログの位置を確認できます。--start-datetime
および--stop-datetime
オプションを使用して、tp
の前後の短い期間を指定し、出力でイベントを探します。 例:shell> mysqlbinlog --start-datetime="2020-03-11 20:05:00" \ --stop-datetime="2020-03-11 20:08:00" --verbose \ /var/lib/mysql/bin.123456 | grep -C 15 "DROP TABLE" /*!80014 SET @@session.original_server_version=80019*//*!*/; /*!80014 SET @@session.immediate_server_version=80019*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 232 #200311 20:06:20 server id 1 end_log_pos 355 CRC32 0x2fc1e5ea Query thread_id=16 exec_time=0 error_code=0 SET TIMESTAMP=1583971580/*!*/; SET @@session.pseudo_thread_id=16/*!*/; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/; SET @@session.sql_mode=1168113696/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C utf8mb4 *//*!*/; SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/; SET @@session.lc_time_names=0/*!*/; SET @@session.collation_database=DEFAULT/*!*/; /*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/; DROP TABLE `pets`.`cats` /* generated by server */ /*!*/; # at 355 #200311 20:07:48 server id 1 end_log_pos 434 CRC32 0x123d65df Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=no original_committed_timestamp=1583971668462467 immediate_commit_timestamp=1583971668462467 transaction_length=473 # original_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT) # immediate_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT) /*!80001 SET @@session.original_commit_timestamp=1583971668462467*//*!*/; /*!80014 SET @@session.original_server_version=80019*//*!*/; /*!80014 SET @@session.immediate_server_version=80019*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 434 #200311 20:07:48 server id 1 end_log_pos 828 CRC32 0x57fac9ac Query thread_id=16 exec_time=0 error_code=0 Xid = 217 use `pets`/*!*/; SET TIMESTAMP=1583971668/*!*/; /*!80013 SET @@session.sql_require_primary_key=0*//*!*/; CREATE TABLE dogs
mysqlbinlog の出力から、
DROP TABLE `pets`.`cats`
ステートメントは# at 232
行と# at 355
行の間のバイナリログのセグメントにあります。つまり、ステートメントはログ位置 232 のあとに実行され、ログはDROP TABLE
ステートメントのあとの位置 355 にあります。注記対象となる実際のイベント位置の検索に役立つのは、
--start-datetime
および--stop-datetime
オプションのみです。 2 つのオプションを使用して適用するバイナリログセグメントの範囲を指定することはお勧めしません: オプションを使用すると、バイナリログイベントが欠落するリスクが高くなります。 かわりに--start-position
および--stop-position
を使用してください。 -
バイナリログファイル内のイベントをサーバーに適用します。これは、手順 1 で見つかったログ位置 (155 であると仮定) から始まり、手順 2 で見つけた、目的の時点 (232) より前の位置で終わります:
shell> mysqlbinlog --start-position=155 --stop-position=232 /var/lib/mysql/bin.123456 \ | mysql -u root -p
このコマンドは、すべてのトランザクションを開始位置から停止位置の直前までリカバリします。 mysqlbinlog の出力には各 SQL ステートメントが記録される前に
SET TIMESTAMP
ステートメントが含まれるため、リカバリされたデータおよび関連する MySQL ログには、トランザクションが実行された元の時間が反映されます。これで、テーブル
pets.cats
が削除される直前に、データベースが目的の時点であるtp
にリストアされました。 -
終了した point-in-time リカバリを超えて、目的の時点の後にすべてのステートメントも再実行する場合は、mysqlbinlog を再度使用して、
tp
の後のすべてのイベントをサーバーに適用します。 ステップ 2 では、スキップするステートメントの後、ログは 355 の位置にあります。これを--start-position
オプションに使用して、位置の後のステートメントを含めることができます:shell> mysqlbinlog --start-position=355 /var/lib/mysql/bin.123456 \ | mysql -u root -p
データベースはバイナリログファイルに記録された最新のステートメントを復元しましたが、選択したイベントはスキップされました。