MySQL GTID マスターとスレーブの不一致を修復するソリューション

MySQL GTID マスターとスレーブの不一致を修復するソリューション

解決策1: レプリカを再構築する

MySQL 5.6 以降では、レプリケーションで新しいグローバル トランザクション ID (GTID) のサポートが導入されています。 GTID モードを有効にして MySQL および MySQL 5.7 のバックアップを実行すると、Percona XtraBackup は GTID 値を xtrabackup_binlog_info に自動的に保存します。 この情報を使用して、新しい GTID ベースのレプリカを作成 (または破損したレプリカを修復) できます。

前提条件

Percona xtrabackupをMySQLマシンにインストールする必要があります

アドバンテージ

比較的安全で操作が簡単

欠点

  • データ量が多い場合、バックアップ時間は長くなります。
  • データベースが読み取りと書き込みを分離している場合、スレーブによって行われた読み取り要求はマスターに転送される必要がある。

手順

マスター

現在のデータベースをバックアップするには、マスター上の xtrabackup ツールを使用してください。このコマンドを実行するユーザーには、MySQL データ ディレクトリを読み取る権限が必要です。

innobackupex --default-file=/etc/my.cnf --user=root -H 127.0.0.1 --password=[パスワード] /tmp

バックアップファイルをスレーブマシンにコピーする

奴隷

スレーブマシンでこのコマンドを実行してバックアップファイルを準備します

innobackupex --default-file=/etc/my.cnf --user=root -H 127.0.0.1 --password=[パスワード] --apply-log /tmp/[タイムスタンプ]

スレーブデータディレクトリをバックアップして削除する

systemctl を停止します。
mv /data/mysql{,.bak}

バックアップをターゲットディレクトリにコピーし、対応する権限を付与してからスレーブを再起動します。

innobackupex --default-file=/etc/my.cnf --user=root -H 127.0.0.1 --password=[パスワード] --copy-back /tmp/[タイムスタンプ]
chmod 750 /データ/mysql
chown mysql.mysql -R /data/mysql
systemctl で mysqld を起動します。

次の例に示すように、実行された現在のバックアップの最後のGTIDを表示します。

$ cat /tmp/[タイムスタンプ]/xtrabackup_binlog_info
mysql-bin.000002 1232 c777888a-b6df-11e2-a604-080027635ef5:1-4

この GTID は、innobackupex バックアップが完了した後にも印刷されます。

innobackupex: MySQL バイナリログの位置: ファイル名 'mysql-bin.000002'、位置 1232、最終変更の GTID 'c777888a-b6df-11e2-a604-080027635ef5:1-4'

MySQLにrootとしてログインし、次のように設定します。

NewSlave > マスターをリセットします。
NewSlave > グローバル gtid_purged='c777888a-b6df-11e2-a604-080027635ef5:1-4' を設定します。
NewSlave > マスターを変更
       MASTER_HOST="$masterip",
       MASTER_USER="repl",
       MASTER_PASSWORD="$slavepass",
       マスター自動位置 = 1;
NewSlave > スレーブを開始;

スレーブのレプリケーションステータスが正常かどうかを確認します

NewSlave > スレーブステータスを表示\G
     [..]
     スレーブIO実行中: はい
     スレーブSQL実行中: はい
     [...]
     取得済み_Gtid_Set: c777888a-b6df-11e2-a604-080027635ef5:5
     実行されたGtidセット: c777888a-b6df-11e2-a604-080027635ef5:1-5

レプリカが 5 番の新しいトランザクションを取得したことがわかります。つまり、1 から 5 までのトランザクションはすでにこのレプリカ上に存在します。こうして、新たなレプリカの構築が完了しました。

解決策2: データ修復にpercona-toolkitを使用する

PT ツールキットには、pt-table-checksum と pt-table-sync という 2 つのツールが含まれており、主にマスターとスレーブの整合性を検出し、データの不整合を修復するために使用されます。

前提条件

percona-toolkitツールをMySQLマシンにインストールする必要があります

アドバンテージ

修復速度が速く、スレーブライブラリを停止する必要がない

欠点

操作は複雑です。操作の前にデータベースをバックアップしてください。修復するテーブルには一意制約が必要です。

手順

背景例

IP関係マッピング

| IP | 役割 |
| ---- | ---- |
| 192.168.100.132 | マスター |
| 192.168.100.131 | スレーブ |

復元するテーブル構造が次の通りであると仮定します。

mysql> show テーブル test.t を作成します。
+-------+-------------------------------------
| テーブル | テーブルの作成 |
+-------+-------------------------------------
| t | テーブル `t` を作成する (
 `id` int(11) NULLではない、
 `content` varchar(20) デフォルト NULL,
 主キー (`id`)
) エンジン=InnoDB デフォルト文字セット=latin1 |
+-------+-------------------------------------

通常のマスタースレーブ整合性の場合、マスターとスレーブのデータは次のようになります。

mysql> test.t から * を選択します。
+----+---------+
| ID | コンテンツ |
+----+---------+
| 1 | へ |
| 2 | バ |
+----+---------+
セット内の 2 行 (0.00 秒)

極端な場合、次のようなマスターとスレーブの不整合が発生すると、状況は次のようになります。

  1. 以下に示すように、マスターは ID 3 のレコードを追加しますが、スレーブに同期されず、自動的にスレーブにフェイルオーバーされます。
  2. 古いスレーブが一定期間新しいマスターとして機能した後、新しいレコードがテーブルに追加されます。

古いマスターを再起動した後、古いマスターのデータは次のようになります。

old_master> test.t から * を選択します。
+----+---------+
| ID | コンテンツ |
+----+---------+
| 1 | へ |
| 2 | バ |
| 3 | く |
+----+---------+
セット内の 3 行 (0.00 秒)

New Masterのデータは以下のとおりです。

new_master> test.t から * を選択します。
+----+---------+
| ID | コンテンツ |
+----+---------+
| 1 | へ |
| 2 | バ |
| 3 | cc |
| 4 | dd |
+----+---------+
セット内の 4 行 (0.00 秒)

このとき、古いマスターが新しいマスターのスレーブとして設定されている場合は、次のようなエラーが報告されます。

...Last_IO_Error: バイナリ ログ: 'マスターの SERVER_UUID を使用すると、スレーブにはマスターよりも多くの GTID があります。

オールドマスターのGTIDが255に達したことがわかります。

実行されたGtidセット: 5b750c75-86c2-11eb-af71-000c2973a2d5:1-10、
60d082ee-86c2-11eb-a9df-000c2988edab:1-255

新マスターのGTIDは254のみ

mysql> マスターステータスを表示\G
************************** 1. 行 ****************************
       ファイル:mysql-bin.000001
     位置: 4062
   バイナリログ_Do_DB:
 バイナリログを無視:
実行されたGtidセット: 5b750c75-86c2-11eb-af71-000c2973a2d5:1-2、
60d082ee-86c2-11eb-a9df-000c2988edab:1-254
セット内の 1 行 (0.00 秒)

この時点で、古いマスターがエラーをスキップし、新しいマスターから正常にレプリケートできる状態に古いマスターを復元するように構成します。

old_master> スレーブを停止します。
クエリは正常、影響を受けた行は 0 行、警告は 1 件 (0.00 秒)

old_master> set gtid_next='60d082ee-86c2-11eb-a9df-000c2988edab:254'; --スキップする次のトランザクションのバージョン、GTIDを指定します
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

old_master> 開始します。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

old_master> commit; -- 空のトランザクションを挿入する
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

old_master> set gtid_next='AUTOMATIC'; -- 自動GTIDに復元
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

old_master> スレーブを起動します。
クエリは正常、影響を受けた行は 0 行 (0.13 秒)

すると、古いマスター上でレプリケーションが正常に進行していることがわかります。

mysql>スレーブステータスを表示\G
      ...
       スレーブIO実行中: はい
      スレーブSQL実行中: はい
      ...
      実行されたGtidセット: 5b750c75-86c2-11eb-af71-000c2973a2d5:1-10、
60d082ee-86c2-11eb-a9df-000c2988edab:1-255
        自動位置: 1
     Replicate_Rewrite_DB:
         チャンネル名:
      マスター TLS バージョン:

最後に、新しいマスターのslave_master_infoをクリアします。

new_master> チャネル '' のすべてのスレーブをリセットします。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

new_master> スレーブステータスを表示します\G;
空セット (0.01 秒)

一貫性を検証する

次に、マスターとスレーブの一貫性を検証する必要があります。新しいマスターでpt-table-checksumを実行します。ROWSは4で、DIFFSがあります。

[root@localhost ~]# pt-table-checksum h='127.0.0.1',u='mha',p='[パスワード]',P=3306 --no-check-binlog-format --databases test
すべてのテーブルをチェックサムできるかどうかを確認しています...
チェックサムを開始しています...
      TS エラー 差分行 DIFF_ROWS チャンク スキップされた時間表
03-29T19:24:18 0 1 4 1 1 0 0.322 テスト.t

双方向同期(同期操作によりデータが変更され、操作前にデータのバックアップが実行されます)

同期プロセス中、pt-table-sync はマスター上のデータを変更します。pt-table-sync のパラメータは次のとおりです。

pt-table-sync --databases テスト --bidirectional --conflict-column='*' --conflict-comparison 'newest' h='192.168.100.132',u='mha',p='[パスワード]',P=3306 h='192.168.100.131' --print
--database は実行するデータベースを指定します --bidirectional は双方向同期です --conflict-column は競合が発生したときに列を比較します --conflict-comparison 競合比較戦略です --print は比較結果を出力します --dry-run テストを実行します --execute テストを実行します # 左側の DSN はスレーブです
# 右側のDSNはマスターです

ここでは、比較列として —conflict-name='content' を指定し、この列としては通常、ビジネス主キーが使用されます。実行される文が印刷されているのがわかります

[root@localhost ~]# pt-table-sync --databases test --bidirectional --conflict-column='content' --conflict-comparison 'newest' h='192.168.100.132',u='mha',p='[パスワード]',P=3306 h='192.168.100.131' --print
/*192.168.100.132:3306*/ `test`.`t` を更新し、`content`='cc' を設定し、`id`='3' を制限 1 に設定します。
/*192.168.100.132:3306*/ `test`.`t`(`id`, `content`) に VALUES ('4', 'dd') を挿入します。

次に、ステートメントを実行します

[root@localhost ~]# pt-table-sync --databases test --bidirectional --conflict-column='content' --conflict-comparison 'newest' h='192.168.100.132',u='mha',p='[パスワード]',P=3306 h='192.168.100.131' --execute

次にマスターで再度データ比較を実行すると、データが正常であることがわかります。

[root@localhost ~]# pt-table-checksum h='127.0.0.1',u='mha',p='[パスワード]',P=3306 --no-check-binlog-format --databases test
すべてのテーブルをチェックサムできるかどうかを確認しています...
チェックサムを開始しています...
      TS エラー 差分行 DIFF_ROWS チャンク スキップされた時間表
03-30T12:09:57 0 0 4 0 1 0 0.330 テスト.t

上記は、MySQL GTID マスタースレーブ不整合の修復ソリューションの詳細な内容です。MySQL GTID マスタースレーブ不整合修復の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL はどのようにしてマスターとスレーブの一貫性を確保するのでしょうか?

<<:  iframe に関するいくつかの発見と考察

>>:  JavaScript の構成と継承の説明

推薦する

10秒以内にMySQLデータベースに数百万件のレコードを挿入する実装

まず、次の質問について考えてみましょう。このような膨大な量のデータをデータベースに挿入するには、通常...

vue+el-upload は複数ファイルの動的アップロードを実現します

vue+el-upload 複数ファイルの動的アップロード、参考までに具体的な内容は以下のとおりです...

DockerでPython環境をパッケージ化するプロセスの詳細な説明

docker パッケージング Python 環境の手順は次のとおりです。 1 pip listの下に...

Windows プラットフォームでの MySQL のインストールと設定方法と注意事項

2.1、msiインストールパッケージ2.1.1、インストール特に重要なのは、インストール前に、元の ...

HTML テーブルに複雑なテーブル ヘッダーを実装するためのサンプル コード

複雑な表を作成するには HTML を使用します。複雑なテーブルでは通常、td の rowspan 属...

MySQL の繰り返し読み取りレベルでファントム読み取りを解決できますか?

導入データベース理論についてさらに学んでいくうちに、さまざまな分離レベルによって起こり得る問題につい...

MySQL の全体的なアーキテクチャの紹介

MySQL の全体的なアーキテクチャは、サーバー層とストレージ エンジン層に分かれています。サーバー...

JavaScript で文字列内の最長の単語を見つける 3 つの方法 (推奨)

この記事は、Free Code Camp の基本アルゴリズム スクリプト「文字列内の最長の単語を見つ...

MySQLデータベースのタイムアウト設定を構成する方法の例

目次序文1. JDBCタイムアウト設定2. 接続プールのタイムアウト設定3. MyBatisクエリの...

表面的なウェブデザイン

<br />私はいつもYahooのウェブデザインが素晴らしいと信じてきました。しかし、こ...

React HTML で react を使用する 2 つの方法

基本的な使い方 <!DOCTYPE html> <html lang="...

Vue3は現在のルーティングアドレスを取得します

正解useRouterの使用: // ルーターパス: "/user/:uid" ...

XHTML の一般的なタグ

XHTML タグとは何ですか? XHTML タグ要素は、XHTML ドキュメントの基本的なコンポーネ...

Linux プラットフォームでの Zabbix エージェントのインストールと設定方法

ここでは、Linux プラットフォームでの Zabbix エージェントのインストールと構成について簡...

自動ロック画面機能を実現するjs

1. 使用シナリオこのような要件があるため、システムが開発されました。ユーザーがデスクトップを離れ...