ライブラリを削除して道を走らないで、MySQLデータの回復を詳しく理解します
53944 ワード
日常の仕事では、手ぶれ、条件の書き間違え、表名の書き間違え、生産ライブラリの誤接続によるライブラリ表とデータの誤削除が発生します.では、データさえ回復できなければ、DBAは何が必要ですか.
1はじめに
データ・リカバリの前提でバックアップを行い、binlogをrow形式で開きます.バックアップファイルがなければ、ライブラリテーブルを削除して本当に削除し、lsofに記録があれば、一部のファイルを復元する可能性があります.しかし、ちょうどデータベースがこのテーブルファイルを開いていない場合は、道を走るしかありません.binlogがオンになっていない場合は、データを復元した後、バックアップポイントからのデータがなくなります.binlogフォーマットがrowでない場合、データを誤って操作した後はフラッシュバック操作ができず、バックアップ・リカバリ・プロセスを正直に実行するしかありません.
2直接リカバリ
ダイレクト・リカバリは、バックアップ・ファイルを使用してフル・リカバリを行う最も一般的なシーンです.
2.1 mysqldumpバックアップフルリカバリ
mysqldumpファイルを使用してデータを復元するのは簡単で、実行を直接解凍しました.
2.2 xtrabackupバックアップフルリカバリ
リカバリプロセス:
2.3ポイント・イン・タイム・リカバリに基づく
ポイント・ベースのリカバリはbinlogログに依存します.binlogからバックアップ・ポイントからリカバリ・ポイントまでのすべてのログを探して適用する必要があります.テストしてみましょう.
新しいテストテーブル:
1秒あたり1つのデータを挿入:
バックアップ:
バックアップ時のログの場所を特定します.
2020-06-09 11:01:54という時点に復元すると仮定し、binlogから39654から2020-06-09 11:01:54までのログを検索します.
現在のデータ・エントリ数:
次に、リカバリを実行します.
データの確認:
2020-06-09 11:01:54という時点に回復しました.
3テーブルを復元
3.1 mysqldumpバックアップからテーブルをリカバリ
リカバリするテーブルがmytestだと仮定します.mytest:
3.2 xtrabackupバックアップからテーブルをリカバリ
仮定./backup_xtra_fullディレクトリは、解凍後にログを適用したバックアップファイルです.
3.2.1 MyISAM表
バックアップファイルからテーブルをリカバリするとします.t_myisam.バックアップファイルからt_を見つけるmyisam.frm, t_myisam.MYD, t_myisam.MYIの3つのファイルは、対応するデータディレクトリにコピーされ、MySQLへのアクセスを許可されます.表情をチェック:
3.2.2 Innodb表
バックアップファイルからテーブルをリカバリするとします.t_innodb、リカバリの前提はinnodb_が設定されていることです.file_per_table = on:から新しいインスタンスが始まります. インスタンスに元と同じテーブルを作成します. alter table t_を実行するinnodb discard tablespace; 表領域を削除すると、この操作でt_innodb.ibd削除; バックアップファイルからt_を検索innodb.ibdというファイルは、対応するデータディレクトリにコピーし、許可します. alter table t_を実行するinnodb IMPORT tablespace; 表領域のロード; flush table t_を実行するinnodb;check table t_innodb; チェックリスト; mysqldumpを使用してデータをエクスポートし、リカバリするデータベースにインポートします.
注意:が新しいインスタンスで再dumpを復元するのは、リスクを回避するためであり、テストであれば、元のライブラリで手順2-6を直接操作することができる. は8.0以前のバージョンでのみ有効です.
4ジャンプ誤操作SQL
誤操作をスキップSQLは、drop tabledatabaseなどのフラッシュバックできない操作を実行するために一般的に使用されます.
4.1バックアップ・ファイル・リカバリによるスキップ
4.1.1 GTIDを開かない
バックアップ・ファイルを使用してリカバリする手順と、複数のbinlogを検索する操作とは異なり、ポイント・イン・タイム・リカバリに基づく操作の差は多くありません.例を挙げると、私はここで2つのテーブルaとbを創立して、毎分1本のデータを挿入して、それから全量のバックアップをして、更にテーブルbを削除して、今このSQLをスキップします.
テーブルbを削除した後のデータベースの状態:
1.バックアップ時のログの場所を特定
2.drop table文を実行したposの位置を特定する
結果からdropが存在する文の開始位置は120629であり,終了位置は120747であることが分かる.
3.binglogからこの文をスキップした他のレコードを抽出する
4.バックアップファイルの復元
5.増分データの復元
リカバリ後のステータスは、drop文がスキップされていることがわかります.
4.1.2 GTIDを開く
GTIDを使用すると、エラーのSQLを直接スキップできます.バックアップ時のログの場所を特定します. drop table文を実行したGTID値を探し出す. バックアップ時のログ位置を最新のbinglogログにエクスポートします. バックアップファイルを復元します. はこのGTIDをスキップした. は、ステップ3で得られたインクリメンタルbinlogログを適用する.
4.2遅延ライブラリを使用してスキップ
4.2.1 GTIDを開かない
遅延ライブラリリカバリを使用する重要な操作はstart slave untilです.私はテスト環境で2つのMySQLノードを構築して、ノード2は600秒遅延して、a、bの2つのテーブルを新築して、毎秒1本のデータシミュレーション業務データの挿入を挿入します.
現在のノード2の状態:
現在のノードの2つのテーブル:
ノードでテーブルbを削除する:
次に、このSQLの操作手順をスキップします.
1.遅延ライブラリ同期停止
2.drop table文を実行した前の文のpos位置を見つける
結果からdropが存在する文の前の文の開始位置が35134であることがわかり、35134に同期しました(これは間違っていません).
3.遅延ライブラリをスキップするSQLの前の項目に同期する
ステータスを表示すると、対応するノードに同期されています.
4.SQLをスキップして同期を開始
同期状態を表示し、テーブルbを削除する文はスキップされました.
4.2.2 GTIDを開く
GTIDを使用してスキップする手順は簡単で、スキップするSQLのGTIDと同じトランザクションを実行すればスキップできます.同期を停止します. drop table文を実行したGTIDを探し出す. はこのGTIDの事務を実行する. 同期を継続します. フラッシュバック.
フラッシュバック操作は逆操作であり、例えばdelete from a where id=1を実行すると、フラッシュバックは対応する挿入操作**insert into a(id,...)values(1,...)を実行し、**はデータを誤操作するために使用され、DML文にのみ有効であり、binlogフォーマットをROWにすることが要求される.この章では、使いやすいオープンソースツールを2つ紹介します.
5.1 binlog2sql
binlog 2 sqlは大衆評価オープンソースのbinlogを解析するためのツールであり、フラッシュバック文、プロジェクトアドレスbinlog 2 sqlを生成するために使用することができる.
5.1.1インストール
5.1.2ロールバックSQLの生成
5.2 MyFlash
MyFlashは、美団評価会社の技術工程部が開発・維持しているDML操作をロールバックするツールで、プロジェクトリンクMyFlashです.
制限: binlogフォーマットはrowで、binlog_row_image=full; は5.6と5.7しかサポートしていません. はDML(追加、削除、変更)のみをロールバックできます.
5.2.1インストール
5.2.2使用
ロールバック文を生成するには、次の手順に従います.
実行するとbinlog_が生成されますoutput_base.Flashbackファイルはmysqlbinlogで解析してから使用する必要があります.
1はじめに
データ・リカバリの前提でバックアップを行い、binlogをrow形式で開きます.バックアップファイルがなければ、ライブラリテーブルを削除して本当に削除し、lsofに記録があれば、一部のファイルを復元する可能性があります.しかし、ちょうどデータベースがこのテーブルファイルを開いていない場合は、道を走るしかありません.binlogがオンになっていない場合は、データを復元した後、バックアップポイントからのデータがなくなります.binlogフォーマットがrowでない場合、データを誤って操作した後はフラッシュバック操作ができず、バックアップ・リカバリ・プロセスを正直に実行するしかありません.
2直接リカバリ
ダイレクト・リカバリは、バックアップ・ファイルを使用してフル・リカバリを行う最も一般的なシーンです.
2.1 mysqldumpバックアップフルリカバリ
mysqldumpファイルを使用してデータを復元するのは簡単で、実行を直接解凍しました.
gzip -d backup.sql.gz | mysql -u<user> -h<host> -P<port> -p
2.2 xtrabackupバックアップフルリカバリ
リカバリプロセス:
# : ( )
innobackupex --decompress
# :
innobackupex --apply-log
# :
innobackupex --datadir= --copy-back
2.3ポイント・イン・タイム・リカバリに基づく
ポイント・ベースのリカバリはbinlogログに依存します.binlogからバックアップ・ポイントからリカバリ・ポイントまでのすべてのログを探して適用する必要があります.テストしてみましょう.
新しいテストテーブル:
chengqm-3306>>show create table mytest.mytest \G;
*************************** 1. row ***************************
Table: mytest
Create Table: CREATE TABLE `mytest` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ctime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1秒あたり1つのデータを挿入:
[mysql@mysql-test ~]$ while true; do mysql -S /tmp/mysql.sock -e 'insert into mytest.mytest(ctime)values(now())';date;sleep 1;done
バックアップ:
[mysql@mysql-test ~]$ mysqldump --opt --single-transaction --master-data=2 --default-character-set=utf8 -S /tmp/mysql.sock -A > backup.sql
バックアップ時のログの場所を特定します.
[mysql@mysql-test ~]$ head -n 25 backup.sql | grep 'CHANGE MASTER TO MASTER_LOG_FILE'
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000032', MASTER_LOG_POS=39654;
2020-06-09 11:01:54という時点に復元すると仮定し、binlogから39654から2020-06-09 11:01:54までのログを検索します.
[mysql@mysql-test ~]$ mysqlbinlog --start-position=39654 --stop-datetime='2019-08-09 11:01:54' /data/mysql_log/mysql_test/mysql-bin.000032 > backup_inc.sql
[mysql@mysql-test-83 ~]$ tail -n 20 backup_inc.sql
......
### INSERT INTO `mytest`.`mytest`
### SET
### @1=161 /* INT meta=0 nullable=0 is_null=0 */
### @2='2020-06-09 11:01:53' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
......
現在のデータ・エントリ数:
-- 2020-06-09 11:01:54
chengqm-3306>>select count(*) from mytest.mytest where ctime < '2020-06-09 11:01:54';
+----------+
| count(*) |
+----------+
| 61 |
+----------+
1 row in set (0.00 sec)
--
chengqm-3306>>select count(*) from mytest.mytest;
+----------+
| count(*) |
+----------+
| 80 |
+----------+
1 row in set (0.00 sec)
次に、リカバリを実行します.
#
[mysql@mysql-test ~]$ mysql -S /tmp/mysql.sock < backup.sql
#
[mysql@mysql-test ~]$ mysql -S /tmp/mysql.sock < backup_inc.sql
データの確認:
chengqm-3306>>select count(*) from mytest.mytest;
+----------+
| count(*) |
+----------+
| 61 |
+----------+
1 row in set (0.00 sec)
chengqm-3306>>select * from mytest.mytest order by id desc limit 5;
+-----+---------------------+
| id | ctime |
+-----+---------------------+
| 61 | 2020-06-09 11:01:53 |
| 60 | 2020-06-09 11:01:52 |
| 59 | 2020-06-09 11:01:51 |
| 58 | 2020-06-09 11:01:50 |
| 57 | 2020-06-09 11:01:49 |
+-----+---------------------+
5 rows in set (0.00 sec)
2020-06-09 11:01:54という時点に回復しました.
3テーブルを復元
3.1 mysqldumpバックアップからテーブルをリカバリ
リカバリするテーブルがmytestだと仮定します.mytest:
#
sed -n '/^-- Current Database: `mytest`/,/^-- Current Database:/p' backup.sql > backup_mytest.sql
#
sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `mytest`/!d;q' backup_mytest.sql > mytest_table_create.sql
#
grep -i 'INSERT INTO `mytest`' backup_mytest.sql > mytest_table_insert.sql
# mytest
mysql -u<user> -p mytest < mytest_table_create.sql
# mytest.mytest
mysql -u<user> -p mytest < mytest_table_insert.sql
3.2 xtrabackupバックアップからテーブルをリカバリ
仮定./backup_xtra_fullディレクトリは、解凍後にログを適用したバックアップファイルです.
3.2.1 MyISAM表
バックアップファイルからテーブルをリカバリするとします.t_myisam.バックアップファイルからt_を見つけるmyisam.frm, t_myisam.MYD, t_myisam.MYIの3つのファイルは、対応するデータディレクトリにコピーされ、MySQLへのアクセスを許可されます.表情をチェック:
chengqm-3306>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| mytest |
| t_myisam |
+------------------+
2 rows in set (0.00 sec)
chengqm-3306>>check table t_myisam;
+-----------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-----------------+-------+----------+----------+
| mytest.t_myisam | check | status | OK |
+-----------------+-------+----------+----------+
1 row in set (0.00 sec)
3.2.2 Innodb表
バックアップファイルからテーブルをリカバリするとします.t_innodb、リカバリの前提はinnodb_が設定されていることです.file_per_table = on:
注意:
4ジャンプ誤操作SQL
誤操作をスキップSQLは、drop tabledatabaseなどのフラッシュバックできない操作を実行するために一般的に使用されます.
4.1バックアップ・ファイル・リカバリによるスキップ
4.1.1 GTIDを開かない
バックアップ・ファイルを使用してリカバリする手順と、複数のbinlogを検索する操作とは異なり、ポイント・イン・タイム・リカバリに基づく操作の差は多くありません.例を挙げると、私はここで2つのテーブルaとbを創立して、毎分1本のデータを挿入して、それから全量のバックアップをして、更にテーブルbを削除して、今このSQLをスキップします.
テーブルbを削除した後のデータベースの状態:
chgnqm-3306>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| a |
+------------------+
1 row in set (0.00 sec)
1.バックアップ時のログの場所を特定
[mysql@mysql-test ~]$ head -n 25 backup.sql | grep 'CHANGE MASTER TO MASTER_LOG_FILE'
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000034', MASTER_LOG_POS=38414;
2.drop table文を実行したposの位置を特定する
[mysql@mysql-test mysql_test]$ mysqlbinlog -vv /data/mysql_log/mysql_test/mysql-bin.000034 | grep -i -B 3 'drop table `b`';
# at 120629
#200618 19:48:30 server id 83 end_log_pos 120747 CRC32 0x6dd6ab2a Query thread_id=29488 exec_time=0 error_code=0
SET TIMESTAMP=1566128910/*!*/;
DROP TABLE `b` /* generated by server */
結果からdropが存在する文の開始位置は120629であり,終了位置は120747であることが分かる.
3.binglogからこの文をスキップした他のレコードを抽出する
# start-position pos ,stop-position drop
mysqlbinlog -vv --start-position=38414 --stop-position=120629 /data/mysql_log/mysql_test/mysql-bin.000034 > backup_inc_1.sql
# start-position drop
mysqlbinlog -vv --start-position=120747 /data/mysql_log/mysql_test/mysql-bin.000034 > backup_inc_2.sql
4.バックアップファイルの復元
[mysql@mysql-test ~]$ mysql -S /tmp/mysql.sock < backup.sql
:
chgnqm-3306>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| a |
| b |
+------------------+
2 rows in set (0.00 sec)
chgnqm-3306>>select count(*) from a;
+----------+
| count(*) |
+----------+
| 71 |
+----------+
1 row in set (0.00 sec)
5.増分データの復元
[mysql@mysql-test ~]$ mysql -S /tmp/mysql.sock < backup_inc_1.sql
[mysql@mysql-test ~]$ mysql -S /tmp/mysql.sock < backup_inc_2.sql
リカバリ後のステータスは、drop文がスキップされていることがわかります.
chgnqm-3306>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| a |
| b |
+------------------+
2 rows in set (0.00 sec)
chgnqm-3306>>select count(*) from a;
+----------+
| count(*) |
+----------+
| 274 |
+----------+
1 row in set (0.00 sec)
4.1.2 GTIDを開く
GTIDを使用すると、エラーのSQLを直接スキップできます.
SET SESSION GTID_NEXT=' GTID ';
BEGIN; COMMIT;
SET SESSION GTID_NEXT = AUTOMATIC;
4.2遅延ライブラリを使用してスキップ
4.2.1 GTIDを開かない
遅延ライブラリリカバリを使用する重要な操作はstart slave untilです.私はテスト環境で2つのMySQLノードを構築して、ノード2は600秒遅延して、a、bの2つのテーブルを新築して、毎秒1本のデータシミュレーション業務データの挿入を挿入します.
localhost:3306 -> localhost:3307(delay 600)
現在のノード2の状態:
chengqm-3307>>show slave status \G;
...
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 15524
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 22845
Relay_Master_Log_File: mysql-bin.000038
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
Seconds_Behind_Master: 600
...
現在のノードの2つのテーブル:
chengqm-3307>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| a |
| b |
+------------------+
ノードでテーブルbを削除する:
chengqm-3306>>drop table b;
Query OK, 0 rows affected (0.00 sec)
chengqm-3306>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| a |
+------------------+
1 row in set (0.00 sec)
次に、このSQLの操作手順をスキップします.
1.遅延ライブラリ同期停止
stop slave;
2.drop table文を実行した前の文のpos位置を見つける
[mysql@mysql-test ~]$ mysqlbinlog -vv /data/mysql_log/mysql_test/mysql-bin.000039 | grep -i -B 10 'drop table `b`';
...
# at 35134
#190819 11:40:25 server id 83 end_log_pos 35199 CRC32 0x02771167 Anonymous_GTID last_committed=132 sequence_number=133 rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 35199
#190819 11:40:25 server id 83 end_log_pos 35317 CRC32 0x50a018aa Query thread_id=37155 exec_time=0 error_code=0
use `mytest`/*!*/;
SET TIMESTAMP=1566186025/*!*/;
DROP TABLE `b` /* generated by server */
結果からdropが存在する文の前の文の開始位置が35134であることがわかり、35134に同期しました(これは間違っていません).
3.遅延ライブラリをスキップするSQLの前の項目に同期する
change master to master_delay=0;
start slave until master_log_file='mysql-bin.000039',master_log_pos=35134;
ステータスを表示すると、対応するノードに同期されています.
chengqm-3307>>show slave status \G;
...
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 65792
...
Slave_IO_Running: Yes
Slave_SQL_Running: No
Exec_Master_Log_Pos: 35134
...
Until_Log_File: mysql-bin.000039
Until_Log_Pos: 35134
4.SQLをスキップして同期を開始
set global sql_slave_skip_counter=1;
start slave;
同期状態を表示し、テーブルbを削除する文はスキップされました.
chengqm-3307>>show slave status \G;
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
1 row in set (0.00 sec)
chengqm-3307>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| a |
| b |
+------------------+
2 rows in set (0.00 sec)
4.2.2 GTIDを開く
GTIDを使用してスキップする手順は簡単で、スキップするSQLのGTIDと同じトランザクションを実行すればスキップできます.
SET SESSION GTID_NEXT=' GTID ';
BEGIN; COMMIT;
SET SESSION GTID_NEXT = AUTOMATIC;
フラッシュバック操作は逆操作であり、例えばdelete from a where id=1を実行すると、フラッシュバックは対応する挿入操作**insert into a(id,...)values(1,...)を実行し、**はデータを誤操作するために使用され、DML文にのみ有効であり、binlogフォーマットをROWにすることが要求される.この章では、使いやすいオープンソースツールを2つ紹介します.
5.1 binlog2sql
binlog 2 sqlは大衆評価オープンソースのbinlogを解析するためのツールであり、フラッシュバック文、プロジェクトアドレスbinlog 2 sqlを生成するために使用することができる.
5.1.1インストール
wget https://github.com/danfengcao/binlog2sql/archive/master.zip -O binlog2sql.zip
unzip binlog2sql.zip
cd binlog2sql-master/
#
pip install -r requirements.txt
5.1.2ロールバックSQLの生成
python binlog2sql/binlog2sql.py --flashback \
-h<host> -P<port> -u<user> -p'' -d<dbname> -t<table_name>\
--start-file='' \
--start-datetime='' \
--stop-datetime='' > ./flashback.sql
python binlog2sql/binlog2sql.py --flashback \
-h<host> -P<port> -u<user> -p'' -d<dbname> -t<table_name> \
--start-file='' \
--start-position= \
--stop-position= > ./flashback.sql
5.2 MyFlash
MyFlashは、美団評価会社の技術工程部が開発・維持しているDML操作をロールバックするツールで、プロジェクトリンクMyFlashです.
制限:
5.2.1インストール
# (centos)
yum install gcc* pkg-config glib2 libgnomeui-devel -y
#
wget https://github.com/Meituan-Dianping/MyFlash/archive/master.zip -O MyFlash.zip
unzip MyFlash.zip
cd MyFlash-master
#
gcc -w `pkg-config --cflags --libs glib-2.0` source/binlogParseGlib.c -o binary/flashback
mv binary /usr/local/MyFlash
ln -s /usr/local/MyFlash/flashback /usr/bin/flashback
5.2.2使用
ロールバック文を生成するには、次の手順に従います.
flashback --databaseNames= --binlogFileNames= --start-position= --stop-position=
実行するとbinlog_が生成されますoutput_base.Flashbackファイルはmysqlbinlogで解析してから使用する必要があります.
mysqlbinlog -vv binlog_output_base.flashback | mysql -u<user> -p