Slide 1

Slide 1 text

その行が(平成に)マスターにINSERTされてから (令和に)スレーブでSELECTされるまで 「それ、違うわよ」君はつぶやいた。「それは、村上龍」と続けたあと、僕の顔をのぞき込む。 「村上龍だったっけ?」僕の言葉が聞こえなかったかのように、物憂げに窓の外に視線を移しながら君は話題を変えた。 「レプリケーション」「レプリケーション?」「そう。レプリケーション。マルチマスターの」 ©sakaik 2019/10/02 yoku0825 日本OSS推進フォーラム アプリケーション部会 第11回勉強会

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

イベントの概要 OSSをITに活用したい技術者および技術者を目指す総ての人々を対象とした、 技術力向上を目的とした技術セミナです。 https://ossforum.connpass.com/event/145515/ 2/77

Slide 4

Slide 4 text

というわけで レプリケーションの基本的な仕組みをおはなしします 活用方法や構築方法には触れません 痛い目を見た話もしません グループレプリケーションは名前だけ出てきます 3/77

Slide 5

Slide 5 text

レプリケーションの基 本的な仕組み だけ をお はなしします(自戒) 4/77

Slide 6

Slide 6 text

レプリケーションの考え方(?) マスター(1台)に対してスレーブ(N台)を構成する 最近はプライマリー, セカンダリーって呼んだりもするみたいですが ‐ マスターに対して更新SQLを投げると スレーブにも更新がかかって同じデータになる 5/77

Slide 7

Slide 7 text

レプリケーションの基本的な仕組み 6/77

Slide 8

Slide 8 text

レプリケーションの基本的な仕組み 7/77

Slide 9

Slide 9 text

レプリケーションの基本的な仕組み 8/77

Slide 10

Slide 10 text

ふしぎなち から 9/77

Slide 11

Slide 11 text

さぞかし高度な技術 を用いて実装されて いるんでしょう? 10/77

Slide 12

Slide 12 text

仕組みそのも のはシンプル 11/77

Slide 13

Slide 13 text

レプリケーションが構成されていない3台の別のサーバーでも 12/77

Slide 14

Slide 14 text

同じことをバックグラ ウンドでやってくれる のがレプリケーション 13/77

Slide 15

Slide 15 text

レプリケーションの基本的な仕組み 14/77

Slide 16

Slide 16 text

レプリケーションの基本的な仕組み 15/77

Slide 17

Slide 17 text

レプリケーションの基本的な仕組み 16/77

Slide 18

Slide 18 text

レプリケーションの基本的な仕組み ふしぎなちからではない 本質的には「マスターに適用された更新のSQLを伝達し、スレーブでリプレイする」 ‐ キーワード バイナリログ, リレーログ ‐ Binlog Dumpスレッド, I/Oスレッド(Receiverスレッド), SQLスレッド(Applierスレッド) ‐ 17/77

Slide 19

Slide 19 text

その行がマスターにINSERTされてからスレーブでSELECTされるまで clientA connection executor storage_engine binlog binlog_dump io_thread relaylog slave_executor sql_thread binlog storage_engine slave_connection clientB master slave 18/77

Slide 20

Slide 20 text

レプリケーションの基本的な仕組み 19/77

Slide 21

Slide 21 text

レプリケーションの区別あれこれ 同期のスタイル 非同期 ‐ 準同期 ‐ 仮想同期 ‐ トポロジー マスター/スレーブ ‐ マルチマスター ‐ イベントの粒度 ステートメント単位 ‐ 行単位 ‐ 20/77

Slide 22

Slide 22 text

レプリケーションの区別あれこれ 同期型 トポロジー ソリューション 非同期 マスター/スレーブ 標準 非同期 マルチマスター (やりようはあるけど推奨しない) 準同期 マスター/スレーブ semisyncプラグイン 準同期 マルチマスター semisyncプラグイン + (やりようはあ るけど推奨しない) 仮想同期 マスター/スレーブ Group Replication(シングルプライマ リーモード) (*) 仮想同期 マルチマスター Group Replication(マルチプライマ リーモード) 仮想同期 マルチマスター Galera Cluster (*) MySQL 8.0.17現在、 super_read_only オプションを利用して制御しているだ けで実体はマルチプライマリーモードと同じ 21/77

Slide 23

Slide 23 text

レプリケーションの区別あれこれ 同期のスタイル 非同期 ‐ 準同期 ‐ 仮想同期 ‐ トポロジー マスター/スレーブ ‐ マルチマスター ‐ 22/77

Slide 24

Slide 24 text

非同期レプリケーション MySQL標準のレプリケーション マスターに対して実行されたSQLはマスターのバイナリログにのみ同期で書き込ま れる 23/77

Slide 25

Slide 25 text

非同期レプリケーション 24/77

Slide 26

Slide 26 text

非同期レプリケーション(again) MySQL標準のレプリケーション マスターに対して実行されたSQLはマスターのバイナリログにのみ同期で書き込ま れる 25/77

Slide 27

Slide 27 text

レプリケーションの区別あれこれ 同期のスタイル 非同期 ‐ 準同期 ‐ 仮想同期 ‐ トポロジー マスター/スレーブ ‐ マルチマスター ‐ 26/77

Slide 28

Slide 28 text

準同期レプリケーション MySQL 5.5とそれ以降に標準でバンドルされているsemisyncプラグインを使う レプリケーションの構築は標準のレプリケーションと同じ semisyncプラグインが有効化されているかされていないかだけで切り替え ‐ マスターに対して実行されたSQLはマスターのバイナリログに書き込まれ、スレー ブのリレーログに書き込まれるまでCOMMITが遅延される 27/77

Slide 29

Slide 29 text

準同期レプリケーション 28/77

Slide 30

Slide 30 text

準同期レプリケーション(again) MySQL 5.5とそれ以降に標準でバンドルされているsemisyncプラグインを使う レプリケーションの構築は標準のレプリケーションと同じ semisyncプラグインが有効化されているかされていないかだけで切り替え ‐ マスターに対して実行されたSQLはマスターのバイナリログに書き込まれ、スレー ブのリレーログに書き込まれるまでCOMMITが遅延される 29/77

Slide 31

Slide 31 text

レプリケーションの区別あれこれ 同期のスタイル 非同期 ‐ 準同期 ‐ 仮想同期 ‐ トポロジー マスター/スレーブ ‐ マルチマスター ‐ 30/77

Slide 32

Slide 32 text

仮想同期レプリケーション MySQL 5.7とそれ以降に標準でバンドルされているgroup_replicationプラグイ ン, またはGarela Replication対応MySQL(Galera Cluster for MySQL, Percona XtraDB Cluster, MariaDB Galera Cluster)を使う 原則マルチマスターで、グループを構成するノード同士で相互にメッシュ状にコ ミュニケーションパスを張る MySQL 8.0.17現在、Group Replicationのシングルプライマリーモードは super_read_only オ プションを利用して制御しているだけで実体はマルチプライマリーモードと同じ ‐ あるノードに対して実行されたSQLはバイナリログ(Galera Clusterの場合は Galera Cacheという別領域)に書き込まれ、他のノードのリレーログに書き込まれ てSQLスレッドが爪を引っ掛けるところまでコミットが遅延される 31/77

Slide 33

Slide 33 text

仮想同期レプリケーション 32/77

Slide 34

Slide 34 text

仮想同期レプリケーション(again) MySQL 5.7とそれ以降に標準でバンドルされているgroup_replicationプラグイ ン, またはGarela Replication対応MySQL(Galera Cluster for MySQL, Percona XtraDB Cluster, MariaDB Galera Cluster)を使う 原則マルチマスターで、グループを構成するノード同士で相互にメッシュ状にコ ミュニケーションパスを張る MySQL 8.0.17現在、Group Replicationのシングルプライマリーモードは super_read_only オ プションを利用して制御しているだけで実体はマルチプライマリーモードと同じ ‐ あるノードに対して実行されたSQLはバイナリログ(Galera Clusterの場合は Galera Cacheという別領域)に書き込まれ、他のノードのリレーログに書き込まれ てSQLスレッドが爪を引っ掛けるところまでコミットが遅延される 33/77

Slide 35

Slide 35 text

仮想同期レプリケーションの特徴 他のスタイルの同期と違い、「更新の競合」を検出するところまでやる 更新が競合したら、どちらか片方はロールバックされる(エラーが返る) ‐ 更新さえ競合しなければあとはスムーズに更新されるであろう、という楽観モデル ではある じゃあ更新が完了するまで待ったら? となると、SQLを受け付けたノードでCOMMIT完了の応 答が返る前に他のノードで更新が完了した行が見えてしまうのでこれ以上はアレだと思う ‐ 34/77

Slide 36

Slide 36 text

レプリケーションの区別あれこれ 同期のスタイル 非同期 ‐ 準同期 ‐ 仮想同期 ‐ トポロジー マスター/スレーブ ‐ マルチマスター ‐ 35/77

Slide 37

Slide 37 text

マスター/スレーブ構成 MySQL標準のレプリケーション構成 スレーブは read_only, super_read_only オプションを利用して書き込みを禁止す るのが良い スレーブに書き込んだSQLはその他のノードに伝搬されない ‐ マスターとスレーブでデータが違う場合、同じSQLをリプレイしても結果が同じになるとは限 らない ‐ 非対称構成なので往々にしてフェイルオーバーが難しい スレーブの切り離しは簡単だけれど ‐ マスターが倒れた場合、既存のスレーブからマスターを選出して新しくレプリケーション構成 を構築しなおす必要がある ‐ 36/77

Slide 38

Slide 38 text

マスター/スレーブ構成 37/77

Slide 39

Slide 39 text

マスター/スレーブ構成(again) MySQL標準のレプリケーション構成 スレーブは read_only, super_read_only オプションを利用して書き込みを禁止す るのが良い スレーブに書き込んだSQLはその他のノードに伝搬されない ‐ マスターとスレーブでデータが違う場合、同じSQLをリプレイしても結果が同じになるとは限 らない ‐ 非対称構成なので往々にしてフェイルオーバーが難しい スレーブの切り離しは簡単だけれど ‐ マスターが倒れた場合、既存のスレーブからマスターを選出して新しくレプリケーション構成 を構築しなおす必要がある ‐ 38/77

Slide 40

Slide 40 text

レプリケーションの区別あれこれ 同期のスタイル 非同期 ‐ 準同期 ‐ 仮想同期 ‐ トポロジー マスター/スレーブ ‐ マルチマスター ‐ 39/77

Slide 41

Slide 41 text

マルチマスター構成 原則として「仮想同期」方式のみの構成 全てのノードに書き込み, 全てのノードから読み取りが可能 グループを構成するノード同士で相互にメッシュ状にコミュニケーションパスを張り、行の更 新情報を相互にやり取りし続ける よってシャーディングのような書き込みのスケールはない MySQL NDB Clusterを除く(アレはバックエンド側でシャーディングしている、ついでにレプリケーション構成ではない) ‐ 対称構成なので単純にラウンドロビンするような構成でもHAが組みやすい 40/77

Slide 42

Slide 42 text

マルチマスター構成 41/77

Slide 43

Slide 43 text

マルチマスター構成(again) 原則として「仮想同期」方式のみの構成 全てのノードに書き込み, 全てのノードから読み取りが可能 グループを構成するノード同士で相互にメッシュ状にコミュニケーションパスを張り、行の更 新情報を相互にやり取りし続ける よってシャーディングのような書き込みのスケールはない MySQL NDB Clusterを除く(アレはバックエンド側でシャーディングしている、ついでにレプリケーション構成ではない) ‐ 対称構成なので単純にラウンドロビンするような構成でもHAが組みやすい 42/77

Slide 44

Slide 44 text

レプリケーションの区別あれこれ 同期のスタイル 非同期 ‐ 準同期 ‐ 仮想同期 ‐ トポロジー マスター/スレーブ ‐ マルチマスター ‐ 43/77

Slide 45

Slide 45 text

レプリケーションの区別あれこれ 同期型 トポロジー ソリューション 非同期 マスター/スレーブ 標準 非同期 マルチマスター (やりようはあるけど推奨しない) 準同期 マスター/スレーブ semisyncプラグイン 準同期 マルチマスター semisyncプラグイン + (やりようはあ るけど推奨しない) 仮想同期 マスター/スレーブ Group Replication(シングルプライマ リーモード) (*) 仮想同期 マルチマスター Group Replication(マルチプライマ リーモード) 仮想同期 マルチマスター Galera Cluster (*) MySQL 8.0.17現在、 super_read_only オプションを利用して制御しているだ けで実体はマルチプライマリーモードと同じ 44/77

Slide 46

Slide 46 text

ひとやすみ 45/77

Slide 47

Slide 47 text

バイナリログイベントの粒度 binlog_format というオプションで設定する 「存在しない行」に対するUPDATEステートメントは binlog_format= STATEMENT では成功する(0行が更新される、シンタックス的に正しいSQL) binlog_format= ROW では失敗する(存在しない行に対する更新だから) ‐ 46/77

Slide 48

Slide 48 text

ステートメント単位のバイナリログ # at 9201 #191001 18:01:49 server id 1080 end_log_pos 9279 CRC32 0x4cb8587f Query thread_id =66 exec_time=0 error_code=0 SET TIMESTAMP=1569920509/*!*/; BEGIN /*!*/; # at 9279 #191001 18:01:49 server id 1080 end_log_pos 9384 CRC32 0xad501739 Query thread_id =66 exec_time=0 error_code=0 SET TIMESTAMP=1569920509/*!*/; INSERT INTO t1 VALUES (1, 'one') /*!*/; # at 9384 #191001 18:01:49 server id 1080 end_log_pos 9415 CRC32 0x44cfc96a Xid = 1006236 COMMIT/*!*/; 47/77

Slide 49

Slide 49 text

行単位のバイナリログ # at 9494 #191001 18:01:58 server id 1080 end_log_pos 9567 CRC32 0x6b37180c Query thread_id=66 exec_time=0 error_code=0 SET TIMESTAMP=1569920518/*!*/; BEGIN /*!*/; # at 9567 #191001 18:01:58 server id 1080 end_log_pos 9621 CRC32 0x53a02174 Table_map: `d1`.`t1` mapped to number 176 # at 9621 #191001 18:01:58 server id 1080 end_log_pos 9669 CRC32 0xc3039a50 Write_rows: table id 176 flags: STMT_END_F BINLOG ' BhaTXRM4BAAANgAAAJUlAAAAALAAAAAAAAEAAmQxAAJ0MQACCA8CgAACAQGAAgP8/wB0IaBT BhaTXR44BAAAMAAAAMUlAAAAALAAAAAAAAEAAgAC/wACAAAAAAAAAAN0d29QmgPD '/*!*/; # at 9669 #191001 18:01:58 server id 1080 end_log_pos 9700 CRC32 0x37305aa1 Xid = 1006238 COMMIT/*!*/; 48/77

Slide 50

Slide 50 text

バイナリログイベントの粒度(again) binlog_format というオプションで設定する 「存在しない行」に対するUPDATEステートメントは binlog_format= STATEMENT では成功する(0行が更新される、シンタックス的に正しいSQL) binlog_format= ROW では失敗する(存在しない行に対する更新だから) ‐ 49/77

Slide 51

Slide 51 text

バイナリログの中身 mysql80 68> SHOW BINLOG EVENTS IN 'bin.000017'; +------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------- ----------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------- ----------------+ | bin.000017 | 4 | Format_desc | 1080 | 124 | Server ver: 8.0.17, Binlog ver: 4 | | bin.000017 | 124 | Previous_gtids | 1080 | 235 | 03e3ad7d-ad03-11e9-9dc1-0201a32caf75:1-12, 552f89cd-aded-11e9-9af8-0201a32caf75:1-548869 | | bin.000017 | 235 | Gtid | 1080 | 314 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548870' | | bin.000017 | 314 | Query | 1080 | 392 | BEGIN | | bin.000017 | 392 | Query | 1080 | 497 | use `d1`; INSERT INTO t1 VALUES (1, 'one') | | bin.000017 | 497 | Xid | 1080 | 528 | COMMIT /* xid=1006254 */ | +------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------------- ----------------+ 6 rows in set (0.00 sec) 50/77

Slide 52

Slide 52 text

バイナリログの中身 ちょっと INSERT してから mysql80 68> SELECT * FROM t1; +-----+------+ | num | val | +-----+------+ | 1 | one | +-----+------+ 1 row in set (0.00 sec) mysql80 68> INSERT INTO t1 VALUES (2, 'two'); Query OK, 1 row affected (0.01 sec) mysql80 68> INSERT INTO t1 VALUES (3, 'three'); Query OK, 1 row affected (0.00 sec) mysql80 68> SELECT * FROM t1; +-----+-------+ | num | val | +-----+-------+ | 1 | one | | 2 | two | | 3 | three | +-----+-------+ 3 rows in set (0.00 sec) 51/77

Slide 53

Slide 53 text

バイナリログの中身 mysql80 68> SHOW BINLOG EVENTS IN 'bin.000017'; +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ | bin.000017 | 4 | Format_desc | 1080 | 124 | Server ver: 8.0.17, Binlog ver: 4 | | bin.000017 | 124 | Previous_gtids | 1080 | 235 | 03e3ad7d-ad03-11e9-9dc1-0201a32caf75:1-12, 552f89cd-aded-11e9-9af8-0201a32caf75:1-548869 | | bin.000017 | 235 | Gtid | 1080 | 314 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548870' | | bin.000017 | 314 | Query | 1080 | 392 | BEGIN | | bin.000017 | 392 | Query | 1080 | 497 | use `d1`; INSERT INTO t1 VALUES (1, 'one') | | bin.000017 | 497 | Xid | 1080 | 528 | COMMIT /* xid=1006254 */ | | bin.000017 | 528 | Gtid | 1080 | 607 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548871' | | bin.000017 | 607 | Query | 1080 | 685 | BEGIN | | bin.000017 | 685 | Query | 1080 | 790 | use `d1`; INSERT INTO t1 VALUES (2, 'two') | | bin.000017 | 790 | Xid | 1080 | 821 | COMMIT /* xid=1006261 */ | | bin.000017 | 821 | Gtid | 1080 | 900 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548872' | | bin.000017 | 900 | Query | 1080 | 978 | BEGIN | | bin.000017 | 978 | Query | 1080 | 1085 | use `d1`; INSERT INTO t1 VALUES (3, 'three') | | bin.000017 | 1085 | Xid | 1080 | 1116 | COMMIT /* xid=1006264 */ | +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ 14 rows in set (0.00 sec) 52/77

Slide 54

Slide 54 text

バイナリログの識別 レプリケーションの構築は「スレーブからマスターに対して」「このバイナリログ ファイルのnバイト目以降をくれ」という要求 mysql80> CHANGE MASTER TO master_host = 'hostname.of.master', master_port = 3306, -> master_user = 'replication_username', master_password = 'plain_ password_is_unsecure', -> master_log_file = 'bin.000017', master_log_pos = 1085; 53/77

Slide 55

Slide 55 text

バイナリログの中身 mysql80 68> SHOW BINLOG EVENTS IN 'bin.000017'; +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ | bin.000017 | 4 | Format_desc | 1080 | 124 | Server ver: 8.0.17, Binlog ver: 4 | | bin.000017 | 124 | Previous_gtids | 1080 | 235 | 03e3ad7d-ad03-11e9-9dc1-0201a32caf75:1-12, 552f89cd-aded-11e9-9af8-0201a32caf75:1-548869 | | bin.000017 | 235 | Gtid | 1080 | 314 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548870' | | bin.000017 | 314 | Query | 1080 | 392 | BEGIN | | bin.000017 | 392 | Query | 1080 | 497 | use `d1`; INSERT INTO t1 VALUES (1, 'one') | | bin.000017 | 497 | Xid | 1080 | 528 | COMMIT /* xid=1006254 */ | | bin.000017 | 528 | Gtid | 1080 | 607 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548871' | | bin.000017 | 607 | Query | 1080 | 685 | BEGIN | | bin.000017 | 685 | Query | 1080 | 790 | use `d1`; INSERT INTO t1 VALUES (2, 'two') | | bin.000017 | 790 | Xid | 1080 | 821 | COMMIT /* xid=1006261 */ | | bin.000017 | 821 | Gtid | 1080 | 900 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548872' | | bin.000017 | 900 | Query | 1080 | 978 | BEGIN | | bin.000017 | 978 | Query | 1080 | 1085 | use `d1`; INSERT INTO t1 VALUES (3, 'three') | | bin.000017 | 1085 | Xid | 1080 | 1116 | COMMIT /* xid=1006264 */ | +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ 14 rows in set (0.00 sec) 54/77

Slide 56

Slide 56 text

雑に行とポジションを結びつける +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- bin.000017の235~528 | 2 | two | <--- bin.000017の528~821 | 3 | three | <--- bin.000017の821~1116 +-----+-------+ 55/77

Slide 57

Slide 57 text

こういうことをすると死ぬ +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- bin.000017の235~528 +-----+-------+ mysql80> CHANGE MASTER TO .., master_log_file= 'bin.000017', master_position = 821; +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- bin.000017の235~528 | 3 | three | <--- bin.000017の821~1116 +-----+-------+ 56/77

Slide 58

Slide 58 text

エラーも吐かず にDBAが死ぬ 57/77

Slide 59

Slide 59 text

バイナリログの中身 mysql80 68> SHOW BINLOG EVENTS IN 'bin.000017'; +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ | bin.000017 | 4 | Format_desc | 1080 | 124 | Server ver: 8.0.17, Binlog ver: 4 | | bin.000017 | 124 | Previous_gtids | 1080 | 235 | 03e3ad7d-ad03-11e9-9dc1-0201a32caf75:1-12, 552f89cd-aded-11e9-9af8-0201a32caf75:1-548869 | | bin.000017 | 235 | Gtid | 1080 | 314 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548870' | | bin.000017 | 314 | Query | 1080 | 392 | BEGIN | | bin.000017 | 392 | Query | 1080 | 497 | use `d1`; INSERT INTO t1 VALUES (1, 'one') | | bin.000017 | 497 | Xid | 1080 | 528 | COMMIT /* xid=1006254 */ | | bin.000017 | 528 | Gtid | 1080 | 607 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548871' | | bin.000017 | 607 | Query | 1080 | 685 | BEGIN | | bin.000017 | 685 | Query | 1080 | 790 | use `d1`; INSERT INTO t1 VALUES (2, 'two') | | bin.000017 | 790 | Xid | 1080 | 821 | COMMIT /* xid=1006261 */ | | bin.000017 | 821 | Gtid | 1080 | 900 | SET @@SESSION.GTID_NEXT= '552f89cd-aded-11e9-9af8-0201a32caf75:548872' | | bin.000017 | 900 | Query | 1080 | 978 | BEGIN | | bin.000017 | 978 | Query | 1080 | 1085 | use `d1`; INSERT INTO t1 VALUES (3, 'three') | | bin.000017 | 1085 | Xid | 1080 | 1116 | COMMIT /* xid=1006264 */ | +------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------+ 14 rows in set (0.00 sec) 58/77

Slide 60

Slide 60 text

都内のDBA 1.000000人に聞きました gtid_mode = ONは便利ですか? はい ‐ Yes ‐ 59/77

Slide 61

Slide 61 text

都内のDBA 1.000000人に聞きました gtid_mode = ONは便利ですか? はい (1) ‐ Yes (0) ‐ 60/77

Slide 62

Slide 62 text

圧倒的支持 率() 61/77

Slide 63

Slide 63 text

GTID b7200c05-1e8d-11e7-9e57-0201a32caf75:2006 ←こんな感じのフォーマット コロンの手前までが「サーバー識別子」(マスターの @@server_uuid )、ソースを 追っかけるならSIDNO(Source ID NO) datadir/auto.cnfに保管されるので、リストア時に注意 ‐ コロンの後ろが「トランザクション識別子」(マスター上でトランザクションがコ ミットされた連番)、ソースを追っかけるならGNO(Group NO) トランザクションを一意に識別するだけで、バイナリログのイベントを一意に識別するわけで はない ‐ 62/77

Slide 64

Slide 64 text

GTIDの表現 b7200c05-1e8d-11e7-9e57-0201a32caf75:2006 b7200c05-1e8d-11e7-9e57-0201a32caf75:1-2006 b7200c05-1e8d-11e7-9e57-0201a32caf75:1-2006, 758f64f0-1e93-11e7-a3fc-0201a32caf75:1-99 758f64f0-1e93-11e7-a3fc-0201a32caf75:1-99, 758f64f0-1e93-11e7-a3fc-0201a32caf75:1000-10000 63/77

Slide 65

Slide 65 text

GTIDとI/Oスレッド master_auto_position= 1の場合、「このファイルのこのポジションから寄越 せ!」の代わりに、「この(=スレーブが既に適用済みの)GTID 以外 のバイナ リーログを頼む」になる サーバー側が動的にファイル名とポジションに変換して送信してくれる。 ‐ 64/77

Slide 66

Slide 66 text

GTIDとI/Oスレッド I/OスレッドとBinlog Dumpスレッドがよしなにやってくれるので、 master_log_file と master_log_pos を設定する必要はもうない mysql80> CHANGE MASTER TO master_host = 'hostname.of.master', master_port = 3306, -> master_user = 'replication_username', master_password = 'plain_ password_is_unsecure', -> master_auto_position = 1; 65/77

Slide 67

Slide 67 text

雑に行とGTIDを結びつける +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870 | 2 | two | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548871 | 3 | three | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548872 +-----+-------+ 66/77

Slide 68

Slide 68 text

こういうことをしても +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870 +-----+-------+ mysql80> CHANGE MASTER TO .., master_auto_position = 1; +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870 | 2 | two | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548871 | 3 | three | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548872 +-----+-------+ 67/77

Slide 69

Slide 69 text

こんなことをしても +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870 | 3 | three | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548872 +-----+-------+ mysql80> CHANGE MASTER TO .., master_auto_position = 1; +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870 | 2 | two | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548871 | 3 | three | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548872 +-----+-------+ 68/77

Slide 70

Slide 70 text

死なない 69/77

Slide 71

Slide 71 text

GTIDとSQLスレッド これから実行するトランザクションのGTID( gtid_next )が実行済み(スレーブ 側の gtid_executed に含まれる)の場合、実行しない(スキップする) これによってスレーブクラッシュ時の「リレーログの二重適用」が完全に回避できる ‐ sql/sql_parse.cc:mysql_execute_commandの中で分岐するので、エグゼキューターがそも そも(ほぼ)動かない。 ‐ エグゼキューターなので、SQLスレッドに限らずフツーのスレッドでも同じ動作。 ‐ 70/77

Slide 72

Slide 72 text

行 vs GTID vs ポジション +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870, bin.000017の235~528 | 2 | two | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548871, bin.000017の528~821 | 3 | three | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548872, bin.000017の821~1116 +-----+-------+ 71/77

Slide 73

Slide 73 text

ポジションベースのレプリケーションやバイナリログを使ったロールフォワー ドをしても +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870, bin.000017の235~528 | 2 | two | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548871, bin.000017の528~821 | 3 | three | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548872, bin.000017の821~1116 +-----+-------+ mysql80> CHANGE MASTER TO .., master_log_file = 'bin.000017', master_log_pos = 821; +-----+-------+ | num | val | +-----+-------+ | 1 | one | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548870, bin.000017の235~528 | 2 | two | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548871, bin.000017の528~821 | 3 | three | <--- 552f89cd-aded-11e9-9af8-0201a32caf75:548872, bin.000017の821~1116 <-- 再実行が抑止される +-----+-------+ 72/77

Slide 74

Slide 74 text

死なない 73/77

Slide 75

Slide 75 text

GTID I/Oスレッドに対する「歯抜け防止」とSQLスレッドに対する「二重実行防止」は それぞれ別機能と考えるとわかりやすい ちなみに、I/Oスレッドで「マスターのbinlogがexpireされてこのままだと歯抜けになっちゃう よ?」となるとエラーでレプリケーションが開始できない。親切。 ‐ mysqlbinlogを使ったロールフォワードリカバリは「歯抜け防止」機能が完全には働かないので 注意 gtid_executedが歯抜けになるからわかるっちゃわかる ‐ ポジションベースのレプリケーション構成を理解した上で、それを拡張するものと 理解すると嫌悪感は少ない 最近のMySQLから始めた人はどっちを使ってるんでしょうね… ‐ 74/77

Slide 76

Slide 76 text

その行がマスターにINSERTされてからスレーブでSELECTされるまで clientA connection executor storage_engine binlog binlog_dump io_thread relaylog slave_executor sql_thread binlog storage_engine slave_connection clientB master slave 75/77

Slide 77

Slide 77 text

レプリケーションの基本的な仕組み 76/77

Slide 78

Slide 78 text

Any Questions and/or Suggestions? 77/77