web-dev-qa-db-ja.com

MySQLレプリケーションスレーブは、SET @@ SESSION.GTID_NEXT = 'ANONYMOUS';を検出するとハングします。

最近、Ubuntu Server 16.04にMySQL 5.7の2つの同一のデフォルトインストールをインストールし、バイナリログレプリケーションを実行するように設定しました。これまではこれで問題なく動作していましたが、突然レプリケーションが停止し、スレーブクエリスレッドは何もせずに100%CPUで実行されます。

いくつか検索したところ、スレーブステータスがマスターよりもかなり遅れていることがわかりました。 Relay_Master_Log_Fileおよび位置Exec_Master_Log_Posによって示されるbinlogファイルでmysqlbinlogを使用すると、この位置で実行されるステートメントは次のとおりであることがわかりました。

SET @@SESSION.GTID_NEXT= 'ANONYMOUS';

どういうわけか、このステートメントを実行しようとするとスレーブがハングし、CPU負荷が100%に送られます(これが最初に状況を発見した方法です)。

スレーブがSET GLOBAL sql_slave_skip_counter=1を使用してそのステートメントをスキップすることを除いて、この問題の実際の原因が何であるか、およびこれをどのように解決する必要があるかは不明です。

どんな助けでも本当にいただければ幸いです!

4
mauritslamers

TL; DR:これはおそらく、ROWベースのレプリケーションと組み合わされた不適切なテーブル設計が原因です。

私はこの問題に遭遇しました。古いデータベースを新しいサーバーに移動してレプリケーションをセットアップするように求められました。

スレーブをハングさせるのは、実際には件名のステートメントではないことがわかりました(SET @@ SESSION.GTID_NEXT = 'ANONYMOUS')。このステートメントは、トランザクションの開始時に発行されます。

mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000196' FROM 96754384 LIMIT 5000;
+------------------+-----------+----------------+-----------+-------------+----------------------------------------------+
| Log_name         | Pos       | Event_type     | Server_id | End_log_pos | Info                                         |
+------------------+-----------+----------------+-----------+-------------+----------------------------------------------+
| mysql-bin.000196 |  96754384 | Anonymous_Gtid |         1 |    96754449 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'         |
| mysql-bin.000196 |  96754449 | Query          |         1 |    96754537 | BEGIN                                        |
| mysql-bin.000196 |  96754537 | Table_map      |         1 |    96754608 | table_id: 241 (db.bad_table)                 |
| mysql-bin.000196 |  96754608 | Delete_rows    |         1 |    96762805 | table_id: 241                                |
| mysql-bin.000196 |  96762805 | Delete_rows    |         1 |    96771002 | table_id: 241                                |
...
| mysql-bin.000196 | 106681175 | Delete_rows    |         1 |   106689372 | table_id: 241                                |
| mysql-bin.000196 | 106689372 | Delete_rows    |         1 |   106697569 | table_id: 241                                |
| mysql-bin.000196 | 106697569 | Delete_rows    |         1 |   106697626 | table_id: 241 flags: STMT_END_F              |
| mysql-bin.000196 | 106697626 | Xid            |         1 |   106697657 | COMMIT /* xid=28382600 */                    |
| mysql-bin.000196 | 106697657 | Rotate         |         1 |   106697704 | mysql-bin.000197;pos=4                       |
+------------------+-----------+----------------+-----------+-------------+----------------------------------------------+
1219 rows in set (0.02 sec)

このテーブルには、6600万行あります。主キーまたは一意キーがないことがわかりました。これを担当するクエリは、マスターでインデックススキャンを使用します。

mysql> SHOW VARIABLES LIKE '%binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)

スレーブがこれをROWベースのレプリケーションで複製するには、スレーブで約1200回の全テーブルスキャンを実行する必要があります。ここではおそらく1200はかなり少ない数です。それは数十万に及ぶ可能性があります。レプリケーションは実際に機能しますが、この設計では、「seconds_behind_master」が無制限に大きくなります。

このテーブルに主キーとパーティションを追加します。また、同僚にコードを書き換えて、一括削除が不要になるように依頼します。これには、おそらく列を追加する必要があります。

編集:他の投稿にコメントするのに十分なポイントがないので、ここではコメントをここに追加します。他の人が述べたように、「SET GLOBAL sql_slave_skip_counter = 1」を発行すると、トランザクション全体がスキップされ、データの不整合が生じると思います。私が間違っていたら訂正してください。

簡単な修正は、binlog形式をQUERYまたはMIXEDに変更することです。これらの形式はデータの不整合にもつながる可能性があるため、binlog形式を変更する代わりに、根本原因を見つけて修正することをお勧めします。

5
Pan

現在、同じ問題が発生しています。 RHEL6、Percona 5.7.15-9。これは繰り返し発生する問題であり、1回限りの問題ではないため、ステートメントをスキップすることは一時的な修正にすぎません。私の場合はすぐにまた壊れるでしょう。

私はもう少し掘りました:

ps -eLo %cpu,pid,spid,cmd | grep <mysqld pid>

これにより、すべてのmysqlスレッドのPID(実際にはスレッドID)が取得され、それぞれのCPU使用率が示されます。私のシステムでは、そのうちの1つだけが比較的高かった(スレーブSQLスレッドだと思います)。

それから:

strace -s 128 -p <thread-pid>

これにより、read、pread、lseek呼び出しの連続ループが発生しました。それぞれの最初の引数としてファイル記述子があります...常に同じです。そう:

ls -l /proc/<thread-pid>/fd/<id-number-from-strace>

読み込まれるファイルへのシンボリックリンクです。私の場合、それはデータベース内のランダムなMyISAM .MYDファイルでした。そのテーブルの内容はstraceからの文字列の出力と一致しますが、これはすぐにはわかりません(読んでください)。

「テーブルレベルのロックを待機しています」というこのテーブルでは何もできませんでした。レプリケーションを最新の状態に戻すためにステートメントをスキップし、魔法のようにテーブルが再び使用可能になりました。修理、最適化、分析テーブルを行いました。それらのどれも何も報告しなかったが、おそらくこれがとにかく役立つことを願っています。

そうでない場合は、InnoDBに変換します。

0
jakem