MySQLマスター/スレーブレプリケーションシナリオの単一テーブルデータエラーにより、レプリケーションが終了し、迅速に修復する方法

シーンの説明:

スレーブデータベースのテーブルデータがマスターデータベースと一致せず、レプリケーションエラーが発生する場合、データベース全体に大量のデータがあり、スレーブデータベースの再実行に時間がかかります。このテーブルだけでデータを回復するにはどうすればよいですか?
各テーブルの状態に一貫性がないため、単一テーブルのデータを修復することは不可能であると一般に考えられています。
以下は、バックアップ単一テーブルがスレーブデータベースに復元されるときに直面する問題と解決策の一覧です。

1.デモ環境の説明:

Dell物理サーバーr620両方の
ネットワーク環境はイントラネット
マスターです:192.168.1.220
スレーブ:192.168.1.217
OSシステム環境:centos7.8 X86_64最小インストール、close iptables、close selinux
テストソフトウェアバージョン:mysql5.7.27バイナリパッケージ
を事前にGtidに基づいてMySQLマスタースレーブレプリケーションを構成し
て、シミュレーションテストデータ作成し、障害シナリオをシミュレートして、
MySQLマスタースレーブレプリケーション
pt-table-checksumを修復し、修復されたMySQLマスタースレーブレプリケーションデータに一貫性があるかどうかを確認する

2つ目は、マスタースレーブレプリケーションを構成する

MySQLのインストールプロセスは、ここでは説明されていません。

マスタースレーブレプリケーション
を構成してマスターマシンの新しいスレーブを構成するには、mysqldumpがデータを バックアップするときにパラメーター--set-gtid-purged = ONを追加することを忘れないでください。
補足説明:
1.通常のバックアップでは--set-gtid-purged =を追加しますOFFバックアップ時の警告を解決します
[root @ localhost〜]#mysqldump -uroot -p'dXdjVF#(y3lt '--set-gtid-purged = OFF --single-transaction -A -B | gzip> 2020-09-17 .sql.gz
2.マスタースレーブの構築時に作成されるバックアップの場合、-set-gtid-purged = OFFパラメーターを追加する必要はありませんが、-set-gtid-purged = ON
[root @ localhost〜] #mysqldumpを追加する必要があります-uroot -p'dXdjVF#(y3lt '--set-gtid-purged = ON --single-transaction -A -B --master-data = 2 | gzip> 2020-09-17.sql.gz
prompt:
inマスタースレーブレプリケーションを構築するには、オフにしないでください。毎日のバックアップ中にオフにすることができます。--set-gtid-purged =
AUTO、ON、OFF
1 .-- set-gtid-purged = OFFは、毎日のバックアップパラメータで使用できます。 。2
.-- = SET-gtid環境構成からマスターコピーを構築するために必要なoN-Purgedパラメータ

Gtidに基づいてマスター/スレーブレプリケーションを構成する具体的な手順は次のとおりです。

マスターライブラリ:

 grant replication slave on *.* to rep@'192.168.1.217' identified by 'JuwoSdk21TbUser'; flush privileges;
 mysqldump -uroot -p'dXdjVF#(y3lt' --set-gtid-purged=ON --single-transaction -A -B --master-data=2 |gzip > 2020-09-20.sql.gz 

スレーブライブラリ操作:

 [root@mysql02 ~]# mysql < 2020-09-17.sql 
 mysql>  change master to master_host='192.168.1.220',master_user='rep',master_password='JuwoSdk21TbUser',MASTER_AUTO_POSITION = 1;start slave;show slave status\G
ERROR 29 (HY000): File '/data1/mysql/3306/relaylog/relay-bin.index' not found (Errcode: 2 - No such file or directory)
ERROR 29 (HY000): File '/data1/mysql/3306/relaylog/relay-bin.index' not found (Errcode: 2 - No such file or directory)
Empty set (0.00 sec)

その理由は、リレーログのストレージパスがスレーブマシン構成my.cnfで構成されているが、パスがスレーブサーバーに存在せず、エラーが報告されているためです。ディレクトリを作成し、mysql権限を許可してから、マスターを再度変更してください

mkdir -p /data1/mysql/3306/relaylog/
cd /data1/mysql/3306/
chown -R mysql.mysql relaylog
mysql> change master to master_host='192.168.1.220',master_user='rep',master_password='JuwoSdk21TbUser',MASTER_AUTO_POSITION = 1;start slave;show slave status\G

マスター/スレーブレプリケーション構成が完了しました。

3.テストデータを準備し、失敗をシミュレーションする

マスターライブラリでシミュレーションデモテーブルを作成し、タイマーとストアドプロシージャを用意し、定期的にデータをテストテーブルに書き込んで、次のマスタースレーブレプリケーション障害回復のデモ用のテストテーブルの作成を容易にし
ます。

 CREATE TABLE `test_event` (
`id` int(8) NOT NULL AUTO_INCREMENT, 
`username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
`create_time` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`) #主键ID
) ENGINE=innodb AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

タイマーを作成し、現在の時刻から1分後に毎秒データを書き込みます。

delimiter $$
create event event_2 
on schedule every 1 second STARTS   CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
COMMENT 'xiaowu create'
do 
    BEGIN
           insert into test_event(username,password,create_time) values("李四","tomcat",now());
    END $$
delimiter ;

上記の方法と同様に新しいテストテーブルtxtを作成し、定期的にデータを書き込みます

スレーブライブラリのシミュレーションエラー:


 insert into test_event(username,password,create_time) values("李四","tomcat",now());
 insert into test_event(username,password,create_time) values("李四","tomcat",now());
 delete from txt where id=200;

次に、マスターライブラリでid = 200のレコードを削除します
マスター操作:txtから削除id = 200;

この時点で、スレーブライブラリはレプリケーションステータスをチェックし、レプリケーションを停止しています。

[root@mysql02 ~]#  mysql -e "show slave status\G"|grep -A 1 'Last_SQL_Errno'
               Last_SQL_Errno: 1062
               Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '8a9fb9a3-f579-11ea-830d-90b11c12779c:42083' at master log mysql-bin.000001, end_log_pos 18053730. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.

4、障害回復

シーン1

レプリケーションエラーが報告された場合、マスタースレーブレプリケーションは、エラーのスキップやレプリケーションフィルタリングなどの方法を使用して修復されていません。マスターデータベースのデータが更新され、スレーブデータベースのデータがエラー状態のままになっている(GTIDが8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42083であると想定)。
修復手順:
マスターデータベースのバックアップテーブルtest_event(バックアップスナップショットGTIDが8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262であると想定);
スレーブデータベースに復元し、
レプリケーションを開始します。
ここでの問題は、レプリケーションの開始位置が8a9fb9a3-f579-11ea-830d-90b11c12779c:42084であり、ライブラリからのテーブルtest_eventのデータステータスが他のテーブルよりも先行していることです。
8a9fb9a3-f579-11ea-830d-90b11c12779c:42084-42262これらのトランザクションでは、テーブルtest_eventデータを変更するトランザクションがある限り、主キーの競合やレコードの非存在などのレプリケーションエラーが発生します(一方、8a9fb9a3-f579-11ea-830d-90b11c12779c: 1-42084、以前のレプリケーションエラーを報告したトランザクションは、テーブルtを変更したトランザクションである必要があります。
解決策:レプリケーションの開始時にテーブルtを変更するこれらのトランザクションで、8a9fb9a3-f579-11ea-830d-90b11c12779c:42084-42262をスキップします。

正しい修復手順:

  1. マスターデータベースのテーブルtest_eventをバックアップし(バックアップスナップショットGTIDは8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262)、それをスレーブデータベースに復元します。
  2. レプリケーションフィルターの設定、フィルターテーブルt:
    CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE =( 'dbtest01.test_event');
  3. 再生が8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262に達したらコピーを開始し、コピーを停止します(スレーブライブラリのすべてのテーブルのデータはこの時点で同じ状態にあり、一貫しています);
    SQL_AFTER_GTIDS = '8a9fb9a3-f579までスレーブを開始します-11ea-830d-90b11c12779c:1-42262 ';
  4. レプリケーションフィルターを削除して、レプリケーションを通常どおり開始します。
    注:バックアップスナップショットに対応するGTIDを記録するには、ここでmysqldump --single-transaction --master-data = 2を使用します

詳細な手順は次のとおりです。

A.マスターライブラリでレプリケーションを停止させたtest_eventテーブルをダンプするには:

mysqldump -uroot -p'dXdjVF#(y3lt'  --single-transaction dbtest01 test_event --master-data=2 |gzip >$(date +%F).test_event.sql.gz
[root@localhost ~]# mysqldump -uroot -p'dXdjVF#(y3lt'  --single-transaction dbtest01 test_event --master-data=2 |gzip >$(date +%F).test_event.sql.gz
mysqldump: [Warning] Using a password on the command line interface can be insecure.
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. 

B.別のバックアップテーブルのスナップショットgtid値を取得します。

8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262

[root@mysql02 ~]# gzip -d 2020-09-17.test_event.sql.gz
[root@mysql02 ~]# grep -A6 'GLOBAL.GTID_PURGED' 2020-09-17.test_event.sql 
SET @@GLOBAL.GTID_PURGED='8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262';
--
-- Position to start replication or point-in-time recovery from
--
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=18130552;

C.このテーブルをスレーブライブラリに復元します。GTID_EXECUTEDはnull値ではないため、テーブルtest_eventをスレーブライブラリにインポートできません。具体的なエラーは次のとおりです:スレーブ
ライブラリの操作:

[root@mysql02 ~]#  mysql dbtest01 < 2020-09-17.test_event.sql 
ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

 mysql> select  @@GLOBAL.GTID_EXECUTED;
+----------------------------------------------------------------------------------------+
| @@GLOBAL.GTID_EXECUTED                                                                 |
+----------------------------------------------------------------------------------------+
| 5ec577a4-f401-11ea-bf6d-14187756553d:1-2,
8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42082 |
+----------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000001
         Position: 368620
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 5ec577a4-f401-11ea-bf6d-14187756553d:1-2,
8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42082
1 row in set (0.00 sec)

解決策はスレーブライブラリにログインすることです:
mysql> reset master;
この操作は現在のライブラリのGTID_EXECUTED値を空にすることができます

[root@mysql02 ~]#  mysql dbtest01 < 2020-09-17.test_event.sql 

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000001
         Position: 154
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262
1 row in set (0.00 sec)

D.オンラインでコピーフィルターを開く:

mysql> CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('db_name.test_event');
Query OK, 0 rows affected (0.00 sec)

[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'db_name.test_event'
  Replicate_Wild_Ignore_Table: db_name.test_event

E.コピーを開始し、8a9fb9a3-f579-11ea-830d-90b11c12779c:42262に再生するときにコピーを停止します(現時点では、スレーブライブラリのすべてのテーブルのデータは同じ状態で一貫しています)

mysql> START SLAVE UNTIL SQL_AFTER_GTIDS ='8a9fb9a3-f579-11ea-830d-90b11c12779c:42262';
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> 

SQLスレッドは現時点ではありませんが、レプリケーションはエラーを報告しなくなりました。

[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'Last_SQL_Error|Slave_IO|Slave_SQL'
               Slave_IO_State: Waiting for master to send event
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
               Last_SQL_Error: 

F.レプリケーションフィルタリングをオンラインでオフにします。

mysql> CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ();
Query OK, 0 rows affected (0.00 sec)

mysql> 
[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'db_name.test_event|IO_Running|SQL_Running'
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
      Slave_SQL_Running_State: 

G.スレーブレプリケーションSQLスレッドを開始します。


mysql> start slave sql_thread;
Query OK, 0 rows affected (0.04 sec)

マスタースレーブ複製の回復:

[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'IO_Running|SQL_Running'
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates

注:バックアップスナップショットに対応するGTIDを記録するには、ここでmysqldump --single-transaction --master-data = 2を使用します

5、マスタースレーブデータの整合性を確認する

検証ツールpt-table-checksumを使用して検証します。インストールおよび使用方法の詳細については、次のブログ投稿アドレスを参照してください。https
//blog.51cto.com/wujianwei/2409523


[root@localhost bin]# time /usr/local/percona-toolkit/bin/pt-table-checksum h=192.168.1.220,u=ptsum,p='ptchecksums',P=3306 --ignore-databases sys,mysql  --truncate-replicate-table  --replicate=percona.ptchecksums --no-check-binlog-format --nocheck-replication-filters --recursion-method="processlist"   2>&1 | tee 2020-09-18-pt-checksum.log

Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
09-18T07:49:09      0      0     9739          0       4       0   0.747 dbtest01.hlz_ad
09-18T07:49:10      0      0    64143          0       4       0   0.968 dbtest01.hlz_ad_step
09-18T07:49:16      0      0   741424          0      10       0   6.014 dbtest01.hlz_bubble
09-18T07:49:18      0      0   499991          0       5       0   1.610 dbtest01.test01
09-18T07:49:25      0      0  3532986          0      13       0   7.802 dbtest01.test02
09-18T07:49:26      0      0   126863          0       1       0   0.976 dbtest01.test_event
09-18T07:49:27      0      1    30294          0       1       0   0.582 test01.txt

real    1m22.725s
user    0m0.387s
sys 0m0.078s

メインライブラリのtest01.txtテーブルがスレーブのtest01.txtと矛盾していることがわかりました。

理由は次のとおりです。今、シミュレーションのデモでは、スレーブライブラリ
でid = 200 が実行された削除アクションがtxtから削除され、スレーブライブラリテーブルtxtのレコードがマスターライブラリtxtテーブルより1つ少なくなっています。

修理データ:

[root@localhost bin]# /usr/local/percona-toolkit/bin/pt-table-sync h=192.168.1.220,u=ptsum,p=ptchecksums,P=3306 --databases=test01 --tables=test01.txt  --replicate=percona.ptchecksums  --charset=utf8  --transaction --execute

もう一度確認してください。データに一貫性があります


[root@localhost bin]# time /usr/local/percona-toolkit/bin/pt-table-checksum h=192.168.1.220,u=ptsum,p='ptchecksums',P=3306 --ignore-databases sys,mysql  --truncate-replicate-table  --replicate=percona.ptchecksums --no-check-binlog-format --nocheck-replication-filters --recursion-method="processlist"   2>&1 | tee 2020-09-18-pt-checksum.log
Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
09-18T09:48:10      0      0     9739          0       4       0   0.784 dbtest01.hlz_ad
09-18T09:48:11      0      0    64143          0       4       0   0.995 dbtest01.hlz_ad_step
09-18T09:48:16      0      0   741424          0       9       0   4.224 dbtest01.hlz_bubble
09-18T09:48:17      0      0   499991          0       5       0   1.470 dbtest01.test01
09-18T09:48:24      0      0  3532986          0      13       0   6.403 dbtest01.test02
09-18T09:48:24      0      0   133999          0       1       0   0.894 dbtest01.test_event
09-18T09:48:25      0      0    37431          0       1       0   0.511 test01.txt

real    0m15.676s
user    0m0.359s
sys 0m0.055s

合計6つのネチズンテストケース

基本的にシーン1と同じケース2が付属。ここでは詳細には触れず、興味のあるネチズンに任せます。
以下では、シナリオと回復方法について簡単に説明します。

レプリケーションエラーが報告された場合、マスタースレーブレプリケーションは、エラーのスキップやレプリケーションフィルタリングなどの方法を使用して修復できます。マスターとスレーブのデータは常に更新されています。
エラー修復手順:
マスターデータベースのバックアップテーブルt(バックアップスナップショットGTIDがaaaa:1-10000であると想定)
、データベースからのコピーを停止、GTIDがaaaa:1-20000、
テーブルtをスレーブデータベースに復元、
レプリケーションを開始。

理由分析:
ここでの問題は、レプリケーションの開始位置がaaaa:20001、aaaa:10000-20000であることです。これらのトランザクションはスレーブライブラリで再生されません。テーブルtデータを変更するトランザクションがある場合、スレーブライブラリはこのトランザクションを失います。データの一部

解決策:バックアップの開始からレプリケーションの開始まで、テーブルtをロックして、aaaa:10000-20000にテーブルtを変更するトランザクションがないことを確認します。

正しい修理手順:


メインライブラリテーブルtに読み取りロックを追加し、メインライブラリのテーブルtをバックアップ
し、ライブラリからのコピーを停止してテーブルtを復元し、コピーを
開始し、
テーブルtのロックを解除します。

推奨される解決策:テーブルtをロックしたくない場合は、ライブラリからのコピーを直接中断し、シナリオ1を使用して再開できます。これにより、テーブルのロックが回避されます。

おすすめ

転載: blog.51cto.com/wujianwei/2535067