Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

3/25はオンライン記念日 1/39

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

\こんばんは/ yoku0825@とある企業のDBA オラクれない ‐ ポスグれない ‐ マイエスキューエる ‐ 生息域 Twitter: @yoku0825 ‐ Blog: 日々の覚書 ‐ 日本MySQLユーザ会 ‐ MySQL Casual ‐ 3/39

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

What’s InnoDB Cluster? MySQL :: MySQL 8.0 Reference Manual :: 21.1 Introducing InnoDB Cluster 5/39

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

MySQL Router クラスターの構成を隠蔽するためのルーター それ以外は驚くほど何もしていない 8/39

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

MySQL Router メタデータノードに定期的に(デフォルトはTTL=0.5秒)アクセスしてメタデータ キャッシュを作成 メタデータノードにアクセスできなかったりグループレプリケーションが有効でない場合は次 のメタデータノードを試す ‐ メタデータキャッシュに従って destinations の role とか routing_strategy とか を評価して、MySQL Routerのポートと mysqld のポートでルーティングする メタデータノードの情報はdynamic_stateに永続化するけど、メタデータそのもの は永続化しない 10/39

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

MySQL Shell グループレプリケーションの操作と mysql_innodb_cluster_metadata の更新をまと めてやってくれる機能を提供 ドキュメントでは Admin API って呼ばれている機能群 ‐ それ以外は驚くほど何もしていない ノードの監視はグループレプリケーションが、落ちたノードの迂回はMySQL Routerの責務 ‐ MySQL Shellは飽くまでDBAが操作する時のインターフェイス ‐ 12/39

Slide 14

Slide 14 text

Admin API 粒度も保護レベルも全く違う2つの操作をラッピングしてくれている グループレプリケーションの操作 中身は https://dev.mysql.com/doc/refman/8.0/en/replication-statements-group.html のSQL ‐ メタデータ( mysql_innodb_cluster_metadata )の更新 これ自体は単なるInnoDBのテーブル これ自体がグループレプリケーションによって同期されることを前提にしている ‐ 13/39

Slide 15

Slide 15 text

MySQL Shell グループレプリケーションとメタデータは少なくともmysqld的には全く関係のな い2つの別のデータ MySQL Shell(とMySQL Routerもか)がメインで使うのはメタデータの方 ゆえにグループレプリケーション側がおかしくなる(MySQL Shellが予測していない壊れ方をす る)と 稀にだがよくズレる 「意図しておかしくしようと」とか「一度おかしくなると」という意味で ‐ 14/39

Slide 16

Slide 16 text

ひとやすみ 15/39

Slide 17

Slide 17 text

ひとやすみついでに MySQL Routerはそうそうおかしくならない、おかしくなっても再起動すると大体 何とかなる メタデータが壊れない限りは ‐ MySQL Shellは一度おかしくなると相当つらい、メタデータを壊すとMySQL Routerにも影響が出る グループレプリケーションが提供する performance_schema.replication_group_members (こっ ちは編集不可)と mysql_innodb_cluster_metadata (こっちはInnoDBなのでSQLでほげれる) とが「別のもの」だと認識しておくといざという時役に立つ ‐ 16/39

Slide 18

Slide 18 text

再開 17/39

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

フツーのレプリケーションのデータ同期 24/39

Slide 26

Slide 26 text

グループレプリケーションのデータ同期 プライマリーで更新 <-> グループコミュニケーションシステム(GCS) <-> セカ ンダリーのリレーログ 1. GCSがOKを返せばプライマリーでコミット -> ストレージエンジン & バイナリロ グ (ここでコミット完了応答) 2. リレーログ -> アプライヤースレッド -> セカンダリーのストレージエンジン & バイナリログ 3. 25/39

Slide 27

Slide 27 text

グループレプリケーションのデータ同期 26/39

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

グループレプリケーションのデータ同期 仮想完全同期(これ自体はGalera用語)であり、リレーログに入ったあとは(並列化 度合いは強いものの)フツーのレプリケーションと同じような制約を受ける ALTER TABLE はパラレル化できないので、セカンダリーでのApply中は後から来た更新は遅延し ているように外からは見える ‐ SHOW SLAVE STATUS では見えないので performance_schema.replication_group_member_stats を監視することになる ‐ たとえリレーログがどん詰まっていても、Certificationには成功する ‐ 28/39

Slide 30

Slide 30 text

グループレプリケーションのデータ同期 MySQL :: MySQL 8.0 Reference Manual :: 18.1.1.2 Group Replication 29/39

Slide 31

Slide 31 text

グループレプリケーションのデータ同期 ここまでの内容は 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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

取り敢えずこのへんまで調べました このへんまで理解して、 group_replication_* や flow_control_* のパラメーター はきっと何とか戦えるんじゃないかなって気になっている あとは実際に運用する環境が( ゚д゚)ホスィ… 32/39

Slide 34

Slide 34 text

それはさておき(個人の感想です) そんな使えないくらい危なっかしいもの? 雑に「わざと壊し回って」みている感じ、「そりゃあ壊れるわ」みたいなことをしなければ壊 れなさそう super_read_only を引っぺがしてデータをいじったり SET sql_log_bin = OFF してみたり マルチプライマリーモードでDDLしたり() “State: RECOVERING” なノードがいるのにMySQL Shellからトポロジーをゴニョろうとしたり ‐ というか5.7から8.0になってだいぶ枯れてきた印象( bugs.mysql.com の推移をみ る限り ) 33/39

Slide 35

Slide 35 text

それはさておき(個人の感想です) グループレプリケーションは設定が面倒で… 俺は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

Slide 36

Slide 36 text

それはさておき(個人の感想です) 書き込みレイテンシー高くない? NICの性能とかによるはずだけど体感かなり遅い ‐ ちょっと強い準同期レプリケーションだと思って扱えば「まあ、こんなもんじゃない?」 ‐ (フツーのレプリケーションで参照分散させるより更に)読み取りに対して書き込みが十分少ない パターンがベストなんだろうなあ 勿論レイテンシーを飲んだ上で「ちょっと強い準同期レプリケーション」として使うのはありだと思う ‐ 特にGRの都合でロールバックが発生した場合、GRはさっさと諦めるけどSQLを受け付けたノー ドは必死でInnoDBのロールバックをしないといけないのでやたら遅く見えることがある ‐ 35/39

Slide 37

Slide 37 text

それはさておき(個人の感想です) 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

Slide 38

Slide 38 text

それはさておき(個人の感想です) グループレプリケーションの動作を細かく調べるには gdb が便利 Binlog_event_writer::write あたりにブレークポイントを仕掛けると、「プライマリーではコ ミットが完了してないけどセカンダリーにはリレーログが渡ってACKも返ってる」ところが簡 単に表現できる ‐ MySQL ShellやMySQL Routerの動作を知りたい時は general_log = ON が有効 MySQL Routerはフェッチしたメタデータを中で更に判定するからそれはもうコード読むしか なさそうだけど ‐ MySQL Shellは諦めてC++を読む気になれば読んだ方が早い気はする ‐ 37/39

Slide 39

Slide 39 text

それはさておき(個人の感想です) これまで考えて試したこととかはブログにも書いてます(今後増えるかどうかは 謎) 日々の覚書: InnoDB Cluster ‐ 38/39

Slide 40

Slide 40 text

Any Questions and/or Suggestions? 39/39