Upgrade to Pro — share decks privately, control downloads, hide ads and more …

InnoDB Clusterよ、お前は何者なんだ

InnoDB Clusterよ、お前は何者なんだ

2020/03/25 MySQL Casual Talks Online(beta) Vol.1
https://mysql-casual.connpass.com/event/171277/

0deae06ab5d86b39feeec2e23a30b88a?s=128

yoku0825
PRO

March 25, 2020
Tweet

Transcript

  1. InnoDB Clusterよ、お前は何者なんだ 「それ、違うわよ」君はつぶやいた。「それは、村上龍」と続けたあと、僕の顔をのぞき込む。 「村上龍だったっけ?」僕の言葉が聞こえなかったかのように、物憂げに窓の外に視線を移しながら君は話題を変えた。 「レプリケーション」「レプリケーション?」「そう。レプリケーション。マルチマスターの」 ©sakaik 2020/03/25 yoku0825 MySQL Casual

    Talks Online(beta) Vol.1
  2. 3/25はオンライン記念日 1/39

  3.   ( ´-`).oO(SAOみたいに「ほげほげオンライン」って言いたかっただけなんて言えな い… 2/39

  4. \こんばんは/ yoku0825@とある企業のDBA オラクれない ‐ ポスグれない ‐ マイエスキューエる ‐ 生息域 Twitter:

    @yoku0825 ‐ Blog: 日々の覚書 ‐ 日本MySQLユーザ会 ‐ MySQL Casual ‐ 3/39
  5. 免責事項 俺もよくわかってないです 特にグループレプリケーション ‐ 調べてる途中なので間違っているところがあるかも知れません 正しい情報をご存知の方は教えてくだしあ ‐ 特に後半、「プライマリー/セカンダリー」と「マスター/スレーブ」の言い回しが 非常に混じると思います よしなに脳内変換してください

    ‐ 4/39
  6. What’s InnoDB Cluster? MySQL :: MySQL 8.0 Reference Manual ::

    21.1 Introducing InnoDB Cluster 5/39
  7. What’s InnoDB Cluster? 3つのプロセスを協調動作させて “InnoDB Cluster” と呼んでいる MySQL Router ‐

    MySQL Shell ‐ グループレプリケーション(mysqld) ‐ 6/39
  8. What’s InnoDB Cluster? 3つのプロセスを協調動作させて “InnoDB Cluster” と呼んでいる MySQL Router ‐

    MySQL Shell ‐ グループレプリケーション(mysqld) ‐ 7/39
  9. MySQL Router クラスターの構成を隠蔽するためのルーター それ以外は驚くほど何もしていない 8/39

  10. MySQL Router - 用語 メタデータ InnoDB Clusterに参加しているmysqldの情報(主にIPアドレスとport番号) ‐ mysql_innodb_cluster_metadata.instances に格納されている情報と

    performance_schema.repication_group_members を突き合わせている ‐ メタデータノード, メタデータサーバー メタデータをフェッチするためにアクセスする対象 ‐ 初回起動は --bootstrap で指定、それ以降は mysql_innodb_cluster_metadata.instances から 引く `–bootstrap ‐ /var/lib/mysqlrouter/state.json に永続化 ‐ dynamic_state(file) /var/lib/mysqlrouter/state.json のこと ‐ 9/39
  11. MySQL Router メタデータノードに定期的に(デフォルトはTTL=0.5秒)アクセスしてメタデータ キャッシュを作成 メタデータノードにアクセスできなかったりグループレプリケーションが有効でない場合は次 のメタデータノードを試す ‐ メタデータキャッシュに従って destinations の

    role とか routing_strategy とか を評価して、MySQL Routerのポートと mysqld のポートでルーティングする メタデータノードの情報はdynamic_stateに永続化するけど、メタデータそのもの は永続化しない 10/39
  12. What’s InnoDB Cluster? 3つのプロセスを協調動作させて “InnoDB Cluster” と呼んでいる MySQL Router ‐

    MySQL Shell ‐ グループレプリケーション(mysqld) ‐ 11/39
  13. MySQL Shell グループレプリケーションの操作と mysql_innodb_cluster_metadata の更新をまと めてやってくれる機能を提供 ドキュメントでは Admin API って呼ばれている機能群

    ‐ それ以外は驚くほど何もしていない ノードの監視はグループレプリケーションが、落ちたノードの迂回はMySQL Routerの責務 ‐ MySQL Shellは飽くまでDBAが操作する時のインターフェイス ‐ 12/39
  14. Admin API 粒度も保護レベルも全く違う2つの操作をラッピングしてくれている グループレプリケーションの操作 中身は https://dev.mysql.com/doc/refman/8.0/en/replication-statements-group.html のSQL ‐ メタデータ( mysql_innodb_cluster_metadata

    )の更新 これ自体は単なるInnoDBのテーブル これ自体がグループレプリケーションによって同期されることを前提にしている ‐ 13/39
  15. MySQL Shell グループレプリケーションとメタデータは少なくともmysqld的には全く関係のな い2つの別のデータ MySQL Shell(とMySQL Routerもか)がメインで使うのはメタデータの方 ゆえにグループレプリケーション側がおかしくなる(MySQL Shellが予測していない壊れ方をす る)と

    稀にだがよくズレる 「意図しておかしくしようと」とか「一度おかしくなると」という意味で ‐ 14/39
  16. ひとやすみ 15/39

  17. ひとやすみついでに MySQL Routerはそうそうおかしくならない、おかしくなっても再起動すると大体 何とかなる メタデータが壊れない限りは ‐ MySQL Shellは一度おかしくなると相当つらい、メタデータを壊すとMySQL Routerにも影響が出る グループレプリケーションが提供する

    performance_schema.replication_group_members (こっ ちは編集不可)と mysql_innodb_cluster_metadata (こっちはInnoDBなのでSQLでほげれる) とが「別のもの」だと認識しておくといざという時役に立つ ‐ 16/39
  18. 再開 17/39

  19. What’s InnoDB Cluster? 3つのプロセスを協調動作させて “InnoDB Cluster” と呼んでいる MySQL Router ‐

    MySQL Shell ‐ グループレプリケーション(mysqld) ‐ 18/39
  20. グループレプリケーション クラスター内のデータ同期を担当 シングルプライマリーモードにおいてはリーダー選出も担当 ノードの死活監視担当 19/39

  21. グループレプリケーション クラスター内のデータ同期を担当 シングルプライマリーモードにおいてはリーダー選出も担当 ノードの死活監視担当 20/39

  22. コイツが難し いんですよ… 21/39

  23. 補足 以下、「プライマリー」「セカンダリー」とシングルプライマリーモードっぽい用 語を使いますが、「更新クエリーを受け付けたやつ」「それ以外のやつ」くらいの 意味だと思ってください(マルチプライマリーでも概ね一緒) 22/39

  24. フツーのレプリケーションのデータ同期 マスターで更新 -> ストレージエンジン & バイナリログ (非同期レプリケーショ ンの場合ここでコミット完了応答) 1. バイナリログ

    -> Binlog Dump -> I/Oスレッド -> リレーログ (準同期レプリ ケーションの場合ここでコミット完了応答) 2. リレーログ -> SQLスレッド -> スレーブのストレージエンジン & バイナリログ 3. 23/39
  25. フツーのレプリケーションのデータ同期 24/39

  26. グループレプリケーションのデータ同期 プライマリーで更新 <-> グループコミュニケーションシステム(GCS) <-> セカ ンダリーのリレーログ 1. GCSがOKを返せばプライマリーでコミット ->

    ストレージエンジン & バイナリロ グ (ここでコミット完了応答) 2. リレーログ -> アプライヤースレッド -> セカンダリーのストレージエンジン & バイナリログ 3. 25/39
  27. グループレプリケーションのデータ同期 26/39

  28. グループレプリケーションのデータ同期 プライマリーでコミットが成功する 前に リレーログはセカンダリーに渡っている たとえば、プライマリーでバイナリログを書きだす処理にブレークポイントを仕掛けると、コ ミット完了より前にバイナリログを書きだそうとするけどセカンダリーではもうその行が見え る ‐ プライマリーがバイナリログを吐き出す前にクラッシュしてした場合、「コミットはエラーに なってどこにも残らない」または「コミットはエラーになるがどこかのセカンダリーに存在す

    る」 そして「どこかのセカンダリー」にあれば、そこから他のセカンダリーにイベントが渡るはず 少なくとも「どのセカンダリーが一番リレーログを受信したか」は気にしなくても良いけど ‐ 27/39
  29. グループレプリケーションのデータ同期 仮想完全同期(これ自体はGalera用語)であり、リレーログに入ったあとは(並列化 度合いは強いものの)フツーのレプリケーションと同じような制約を受ける ALTER TABLE はパラレル化できないので、セカンダリーでのApply中は後から来た更新は遅延し ているように外からは見える ‐ SHOW SLAVE

    STATUS では見えないので performance_schema.replication_group_member_stats を監視することになる ‐ たとえリレーログがどん詰まっていても、Certificationには成功する ‐ 28/39
  30. グループレプリケーションのデータ同期 MySQL :: MySQL 8.0 Reference Manual :: 18.1.1.2 Group

    Replication 29/39
  31. グループレプリケーションのデータ同期 ここまでの内容は group_replication_applier チャンネル(仮称)のはなし マルチソースレプリケーションで FOR CHANNEL .. を指定した時のように、 performance_schema.replication_*

    テーブルでは channel_name = 'group_replication_applier' で記録される ‐ リレーログの名前も xxx-relay-bin-group_replication_applier.000001 みたいになる ‐ グループレプリケーションにはもう一つ、 group_replication_recovery チャンネ ルがある GCSが起動した時の「差分同期」専用チャンネル ‐ 手でグループレプリケーションを組んだことがある人なら分かるはず。 CHANGE MASTER TO で指 定したアレ ‐ 30/39
  32. group_replication_recoveryチャンネル こっちは比較的フツーのGTID-basedな非同期レプリケーションとして振る舞う ドナー側は SHOW PROCESSLIST で Binlog GTID Dump スレッドが見える

    ‐ レシピエント側では SHOW SLAVE STATUS では見えないけども… ‐ リレーログの名前は xxx-relay-bin-group_replication_recovery.000001 みたいな感じ ‐ このスレッドが動いている間はグループレプリケーションのステータスが “RECOVERING” このスレッドがある程度(GCS起動時にドナーで確認できたgtid_executedまで?)GTIDを適用し 終えるまでは group_replication_applier チャンネルは動作を止めている ‐ しかし “RECOVERING” のノードでもCertificationには参加できるっぽい (ワーストケース で1台ONLINE, 2台RECOVERINGでも成功する) ‐ 31/39
  33. 取り敢えずこのへんまで調べました このへんまで理解して、 group_replication_* や flow_control_* のパラメーター はきっと何とか戦えるんじゃないかなって気になっている あとは実際に運用する環境が( ゚д゚)ホスィ… 32/39

  34. それはさておき(個人の感想です) そんな使えないくらい危なっかしいもの? 雑に「わざと壊し回って」みている感じ、「そりゃあ壊れるわ」みたいなことをしなければ壊 れなさそう super_read_only を引っぺがしてデータをいじったり SET sql_log_bin = OFF

    してみたり マルチプライマリーモードでDDLしたり() “State: RECOVERING” なノードがいるのにMySQL Shellからトポロジーをゴニョろうとしたり ‐ というか5.7から8.0になってだいぶ枯れてきた印象( bugs.mysql.com の推移をみ る限り ) 33/39
  35. それはさておき(個人の感想です) グループレプリケーションは設定が面倒で… 俺はMySQL Shellを使う以外の方法は諦めました ただし SET PERSIST で datadir/mysqld-auto.cnf に容赦なく突っ込んで、コイツは

    --defaults-file とかより優先 されるので注意 ‐ 少なくともオートスケール的な仕組みにするには server_id もランダムに作ってくれるし冪等 だし今のところベストだと思う バグがないとは言ってないので、ここを使い込んでバグを修正してもらう方向に持っていくのが良いと思う MySQL Bugs: #98219: dba.configureInstance() fails by Variable ‘report_port’ is a read only variable ‐ 34/39
  36. それはさておき(個人の感想です) 書き込みレイテンシー高くない? NICの性能とかによるはずだけど体感かなり遅い ‐ ちょっと強い準同期レプリケーションだと思って扱えば「まあ、こんなもんじゃない?」 ‐ (フツーのレプリケーションで参照分散させるより更に)読み取りに対して書き込みが十分少ない パターンがベストなんだろうなあ 勿論レイテンシーを飲んだ上で「ちょっと強い準同期レプリケーション」として使うのはありだと思う ‐

    特にGRの都合でロールバックが発生した場合、GRはさっさと諦めるけどSQLを受け付けたノー ドは必死でInnoDBのロールバックをしないといけないのでやたら遅く見えることがある ‐ 35/39
  37. それはさておき(個人の感想です) binlog_format = ROW が強制されるので、 binlog_rows_query_log_events = ON だ とリレーログやバイナリログの中身確認が捗る

    log_error_verbosity= 3 でないと吐かれるログの量が少なくてつらい group_replication_communication_debug_options= GCS_DEBUG_ALL はだいぶキー プアライブのノイズが載るので最後の手段 performance_schema.replication_group_member_stats テーブルの監視は必須 36/39
  38. それはさておき(個人の感想です) グループレプリケーションの動作を細かく調べるには gdb が便利 Binlog_event_writer::write あたりにブレークポイントを仕掛けると、「プライマリーではコ ミットが完了してないけどセカンダリーにはリレーログが渡ってACKも返ってる」ところが簡 単に表現できる ‐ MySQL

    ShellやMySQL Routerの動作を知りたい時は general_log = ON が有効 MySQL Routerはフェッチしたメタデータを中で更に判定するからそれはもうコード読むしか なさそうだけど ‐ MySQL Shellは諦めてC++を読む気になれば読んだ方が早い気はする ‐ 37/39
  39. それはさておき(個人の感想です) これまで考えて試したこととかはブログにも書いてます(今後増えるかどうかは 謎) 日々の覚書: InnoDB Cluster ‐ 38/39

  40. Any Questions and/or Suggestions? 39/39