はじめに
MySQL Database Service (以下 MDS) は自動バックアップの機能がありますが、
DBの運用ではバックアップからのリストアだけでなく、ポイントインタイムリカバリを行いたい場合もあるかと思います。
今回はOracleの以下のブログ記事で紹介されているMDSでのポイントインタイムリカバリを試してみました。
https://blogs.oracle.com/mysql/point-in-time-recovery-in-oci-mds-with-object-storage-%E2%80%93-part-1
https://blogs.oracle.com/mysql/point-in-time-recovery-in-oci-mds-with-object-storage-%e2%80%93-part-2
事前準備
以下の準備が事前に必要となります。
- MDSの作成
- バックアップ計画
- コンピュートインスタンス作成
- オブジェクトストレージバケット作成
本記事ではオブジェクトストレージバケット作成のみ説明します。
MDSの作成についてはこちらの記事で、バックアップの作成はこちらの記事でも紹介しております。
バケット作成
バケットはオブジェクト・ストレージとアーカイブ・ストレージ -> バケット から作成します。
バケット作成を選択し、名前などを定義変更した後に作成ボタンを選択します。
バケットについて詳しくはこちらのドキュメントをご参照ください。
また。CLIを使用したバケットの作成方法は弊社ブログのこちらの記事でも触れられています。
バイナリログの保存
必要なパッケージを事前準備で作成したコンピュート・インスタンスにインストールします。
s3fs-fuseのインストールにはEPELが必要です。
1 2 3 4 |
# yum –y install mysql-community-client # yum –y install mysql-shell # yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm # yum -y install s3fs-fuse |
次に、オブジェクトストレージバケットにアクセスするためのキーを取得します。
プロファイルのユーザー設定を選択
顧客秘密キーに移動し、秘密キーの生成ボタンを選択する
適当な秘密キーの名前を入力し、秘密キーの生成ボタンを選択する
生成されたキーが表示されます。このキーは控えておきます。
リストから生成したキーのアクセスキーも確認します。
アクセスキーにマウスオーバーするとコピーすることができため、これも控えておきます。
控えた秘密キーとアクセスキーを任意のファイルに記載します。
キーは1行でコロン区切りで<アクセスキー>:<秘密キー>
の形式で記載します。
例えば、アクセスキーがhherk4eq9xp236exkyi8rtt3
、秘密キーがvb4hysn+jn/mr5h8+43nfvk+6a
の場合は以下のようになります。
1 2 |
# vi ~/.passwd-ocifs hherk4eq9xp236exkyi8rtt3:vb4hysn+jn/mr5h8+43nfvk+6a |
作成したファイルのパーミッションを変更します。
1 |
# chmod 600 ~/.passwd-ocifs |
ディレクトリを作成し、オブジェクトストレージのバケットをマウントします。
1 2 3 4 |
# mkdir /mnt/oci # s3fs ss-bucket /mnt/oci -o passwd_file=~/.passwd-ocifs \ -o url=https://XXXXXXX.compat.objectstorage.ap-tokyo-1.oraclecloud.com/ \ -o nomultipart -o use_path_request_style |
s3fsコマンドは以下のように指定します
1 2 3 |
s3fs [バケット名] [ディレクトリ] -o passwd_file=[キーファイルのパス] \ -o url=https://[ネームスペース名].compat.objectstorage.[リージョン].oraclecloud.com/ \ -o nomultipart -o use_path_request_style |
- バケット名は本手順の最初に作成したバケットの名前です
- ディレクトリは直前に作成したディレクトリのパスです
- キーファイルのパスは事前に作成した秘密キーとアクセスキーのファイルのパスです
- ネームスペース名はアカウント作成時に割り当てられます。
プロファイル -> テナンシから確認することができます。
マウントできたかどうかを確認してみます。/mnt/oci/
にファイルを一つ作成します。
1 |
# touch /mnt/oci/test_20210922.txt |
作成したss-bucket
のオブジェクトを確認すると、先ほど作成したファイルが存在していることが確認できます。
バイナリログの取得
次にMDSインスタンスからバイナリログを取得し、/mnt/ociにストリーミングする設定をします。
専用のMySQLユーザーを作成します。
1 2 3 4 5 |
mysql> CREATE USER 'binlog_to_object_storage'@'10.0.0.%' IDENTIFIED BY 'Password1!' REQUIRE SSL; mysql> GRANT REPLICATION SLAVE ON *.* TO 'binlog_to_object_storage'@'10.0.0.%'; mysql> GRANT SELECT ON performance_schema.file_instances TO 'binlog_to_object_storage'@'10.0.0.%'; |
mysql_config_editorを使用して接続情報を保存します。
1 2 3 |
# mysql_config_editor set --login-path=my-mds --host=10.0.1.122 \ --user=binlog_to_object_storage --password Enter password: |
mysqlbinlogは--read-from-remote-server
オプションを使用することでサーバーに接続してバイナリログを要求し、それをファイルに書き出すことができます。この機能を利用して、バイナリログを取得します。これにはREPLICATION SLAVE
権限が必要です。
1 2 |
# mysqlbinlog --login-path=<login-path> --raw --read-from-remote-server \ --stop-never <log_file> |
今回は、参照元のブログ記事に従いこのbinlog_to_object_storage.shを使用します。
スクリプト内でperformance_schema.file_instances
に対して、SELECTを実行するため、SELECT
権限も必要となります。
このスクリプトを/root/bin/
に配置します。
1 2 3 |
# mkdir /root/bin # mv binlog_to_object_storage.sh /root/bin/ # chmod +x /root/bin/binlog_to_object_storage.sh |
設定ファイルを作成します。
ファイルを作成には作成したログインパス、ディレクトリを指定します。
1 2 3 4 5 |
# mkdir /root/conf # vi /root/conf/my-mds.conf MYSQL_LOGIN_PATH=my-mds OBJECT_STORAGE_MOUNT=/mnt/oci BINLOGS_DIR=my-mds |
次にプロセスを開始するためのsystemdサービススクリプトを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# vi /etc/systemd/system/binlog_streaming@.service [Unit] Description=Streaming MDS binary logs to Object Storage using %i After=network.target [Service] Type=simple User=root Restart=on-failure ExecStart=/root/bin/binlog_to_object_storage.sh /root/conf/%i.conf [Install] WantedBy=multi-user.target |
デーモンをリロードした後、binlog_streaming@my-mds.service
をスタートします。
1 2 |
# systemctl daemon-reload # systemctl start binlog_streaming@my-mds.service |
起動していることを確認します。
1 2 3 4 5 6 7 8 |
# systemctl status binlog_streaming@my-mds.service binlog_streaming@my-mds.service - Streaming MDS binary logs to Object Storage using my-mds Loaded: loaded (/etc/systemd/system/binlog_streaming@.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2021-09-22 06:23:09 GMT; 3s ago Main PID: 1104 (binlog_to_objec) CGroup: /system.slice/system-binlog_streaming.slice/binlog_streaming@my-mds.service ├─1104 /bin/bash /root/bin/binlog_to_object_storage.sh /root/conf/my-mds.conf └─1121 /bin/mysqlbinlog --login-path=my-mds --raw --read-from-remote-server --stop-never binary-log.000005 |
/mnt/oci
を確認するとログを取得できていることが確認できます。
1 2 3 4 |
# ls /mnt/oci/my-mds/ binary-log.000005 binary-log.000008 binary-log.000011 binary-log.000014 binary-log.000017 binary-log.000006 binary-log.000009 binary-log.000012 binary-log.000015 binary-log.000018 binary-log.000007 binary-log.000010 binary-log.000013 binary-log.000016 |
バケットからもバイナリログが保存されていることが確認できます。
ポイントインタイムリカバリ
ストリーミングしたバイナリログを用いてリカバリを実施します。
事前準備
シナリオで使用するテーブルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 |
mysql> create database d1; mysql> create table d1.t1 (c1 int , c2 varchar(10)); mysql> insert into d1.t1 values(1,"aaa"),(2,"bbb"),(3,"ccc"); mysql> select * from d1.t1; +------+------+ | c1 | c2 | +------+------+ | 1 | aaa | | 2 | bbb | | 3 | ccc | +------+------+ 3 rows in set (0.00 sec) |
完全バックアップを手動で取得します。
取得方法はこちらの記事をご参照ください。
シナリオ
オペレーションミスを想定し、d1.t1からデータを削除してしまいます。
データを削除する前の状態までデータベースを戻します
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
mysql> insert into d1.t1 values(4,"ddd"); mysql> insert into d1.t1 values(5,"eee"); mysql> insert into d1.t1 values(6,"fff"); mysql> delete from d1.t1 where c2 = "ccc"; mysql> insert into d1.t1 values(7,"ggg"); mysql> insert into d1.t1 values(8,"hhh"); mysql> insert into d1.t1 values(9,"iii"); mysql> select * from d1.t1; +------+------+ | c1 | c2 | +------+------+ | 1 | aaa | | 2 | bbb | | 4 | ddd | | 5 | eee | | 6 | fff | | 7 | ggg | | 8 | hhh | | 9 | iii | +------+------+ 8 rows in set (0.00 sec) |
まずはバイナリログから該当のDELETE文を探します。
今回はDELETE文がdelete from d1.t1 where c2 = "ccc";
であることがわかっているため、”ccc”でバイナリログを探してみます。
1 2 3 4 5 |
# grep ccc /mnt/oci/my-mds/* Binary file /mnt/oci/my-mds/binary-log.000029 matches Binary file /mnt/oci/my-mds/binary-log.000030 matches Binary file /mnt/oci/my-mds/binary-log.000031 matches Binary file /mnt/oci/my-mds/binary-log.000033 matches |
複数ヒットしましたが、該当のDELETE文は直近のバイナリログの方にあると考えられるため、binary-log.000033の方をmysqlbinlog
コマンドで詳しく見てみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# mysqlbinlog -v --base64-output=DECODE-ROWS /mnt/oci/my-mds/binary-log.000033 | less (略) /*!80001 SET @@session.original_commit_timestamp=1632884294421670*//*!*/; /*!80014 SET @@session.original_server_version=80026*//*!*/; /*!80014 SET @@session.immediate_server_version=80026*//*!*/; SET @@SESSION.GTID_NEXT= '5d7d91f1-1b62-11ec-ad40-02001700c0e4:27'/*!*/; # at 1283 #210929 2:58:14 server id 835880750 end_log_pos 1354 CRC32 0x12686c6e Query thread_id=13 exec_time=0 error_code=0 SET TIMESTAMP=1632884294/*!*/; BEGIN /*!*/; # at 1354 # at 1412 #210929 2:58:14 server id 835880750 end_log_pos 1466 CRC32 0x804eb9e6 Table_map: `d1`.`t1` mapped to number 100 # at 1466 #210929 2:58:14 server id 835880750 end_log_pos 1510 CRC32 0xeff51a07 Delete_rows: table id 100 flags: STMT_END_F ### DELETE FROM `d1`.`t1` ### WHERE ### @1=3 ### @2='ccc' # at 1510 (略) |
DELETE文のGTIDは以下のようになっていることがわかります。
1 |
SET @@SESSION.GTID_NEXT= '5d7d91f1-1b62-11ec-ad40-02001700c0e4:27'/*!*/; |
取得したバックアップをリストアします。リストア方法はこちらの記事をご参照ください。
リストアしたDBに接続し、GTIDセットを確認します。
1 2 3 4 5 6 7 |
mysql> select @@gtid_executed; +-------------------------------------------+ | @@gtid_executed | +-------------------------------------------+ | 5d7d91f1-1b62-11ec-ad40-02001700c0e4:1-23 | +-------------------------------------------+ 1 row in set (0.00 sec) |
テーブルはバックアップを取ったときの状態です。
1 2 3 4 5 6 7 8 9 |
mysql> select * from d1.t1; +------+------+ | c1 | c2 | +------+------+ | 1 | aaa | | 2 | bbb | | 3 | ccc | +------+------+ 3 rows in set (0.00 sec) |
gtid_executed が5d7d91f1-1b62-11ec-ad40-02001700c0e4:1-23
DELETE文のGTIDが5d7d91f1-1b62-11ec-ad40-02001700c0e4:27
であるため、
今回は5d7d91f1-1b62-11ec-ad40-02001700c0e4:24-26
までを含めます。
以下のコマンドでバイナリログを適用します。
1 2 3 |
# cd /mnt/oci/my-mds/ # mysqlbinlog --require-row-format binary-log.0000[0-3]* \ --include-gtids='5d7d91f1-1b62-11ec-ad40-02001700c0e4:24-26' | mysql -pPassword1! -h10.0.1.205 |
リストアしたDBに接続してみると、DELETEを実行する直前までデータが復元されていることが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 |
mysql> select * from d1.t1; +------+------+ | c1 | c2 | +------+------+ | 1 | aaa | | 2 | bbb | | 3 | ccc | | 4 | ddd | | 5 | eee | | 6 | fff | +------+------+ 6 rows in set (0.00 sec) |
まとめ
MDSからmysqlbinlogを取得し、バケットに保持する手順とバックアップとバイナリログを用いてポイントインタイムリカバリを実行する手順を確認しました。
また、今回の検証では触れませんでしたが、ライフサイクル・ルールを作成しバケット内のオブジェクトの保持期間を設定することができます。この機能を用いて、古いバイナリログはアーカイブ層に移動させたり、削除したりするといいでしょう。