MySQL5.7 GA の Multi-threaded slave

90
MySQL5.7 GA Multi-Threaded Slave 瀬島 貴則 瀬島 貴則

Transcript of MySQL5.7 GA の Multi-threaded slave

Page 1: MySQL5.7 GA の Multi-threaded slave

MySQL5.7 GA のMulti-Threaded Slave瀬島 貴則瀬島 貴則

Page 2: MySQL5.7 GA の Multi-threaded slave

免責事項

- 本資料は個人の見解であり、私が所属する組織の見解とは必ずしも一致しません。

- 内容の一部に偏ったものがあるかもしれませんが、各自オトナの判断でよろしくお願いします。

- MySQL 5.7.12 や 5.7.13を読みつつ書いてます。最近はGAリリース以降も機能追加されたりするので、そのへんはご了承下さい。

Page 3: MySQL5.7 GA の Multi-threaded slave

自己紹介

- わりとMySQLでごはんたべてます- 一時期は Resource Monitoring もよくやってました

- Twitter: @ts4th

Page 4: MySQL5.7 GA の Multi-threaded slave

ちょっと宣伝

- 最近はわりとスライドを公開してますので- よろしかったら参考までに

- http://www.slideshare.net/takanorisejima

Page 5: MySQL5.7 GA の Multi-threaded slave

今日のお題

- MySQL5.7 GA で Multi-Threaded Slave(MTS) が改善されました

- --slave-parallel-type=LOGICAL_CLOCK が追加されて、一見、良さそうなんですが

- その実装についてまとめられた記事をみかけないので、ざっくりまとめてみました

- 有識者からのマサカリ歓迎します

Page 6: MySQL5.7 GA の Multi-threaded slave

というかぶっちゃけ

- 自分でもコード読んでて難しいなと思ったので- 「ここって正確にはこうじゃない?」と思った有識者の方は

- 積極的にマサカリ投げてください- むしろ投げて

Page 7: MySQL5.7 GA の Multi-threaded slave

では、

はじめます

Page 8: MySQL5.7 GA の Multi-threaded slave

5.7で導入された LOGICAL_CLOCK

- MySQL 5.6 の MTS の実装である slave-parallel-type=DATABASE と異なり、 同じ DATABASE でも、 slave が複数 thread で更新可能

- MySQL の伝統的な replication は SQL_Thread がシングルスレッドであるがゆえに、 master の更新頻度が高いと slave の SQL_Thread がボトルネックになって、 replication の遅延が発生することがあった

- master は複数の Thread で更新処理を実行できたが、 slave は SQL_Thread のみで更新する実装だった

Page 9: MySQL5.7 GA の Multi-threaded slave

夢のような機能ではあるけれど

- どのようにして、同時実行可能だと判断するのか?

- slave が複数の Thread で更新する場合、slave の整合性はどうやって保たれるのか?- master の binlog とどうやって見比べれば良いのか?

- stop slave したときの振る舞いは?- master <-> slave 間の connection が切れたとき、再接続や retry は?

Page 10: MySQL5.7 GA の Multi-threaded slave

込み入った実装について書いてあるドキュメントや blog 等が見当たらないので、どうやって実現しているのかがわからない

Page 11: MySQL5.7 GA の Multi-threaded slave

よろしいならば

Page 12: MySQL5.7 GA の Multi-threaded slave

コードを読もう

Page 13: MySQL5.7 GA の Multi-threaded slave

だがしかし

Page 14: MySQL5.7 GA の Multi-threaded slave

なにこれ

むずかしい

Page 15: MySQL5.7 GA の Multi-threaded slave

コードだけでは難しいので、

先ずは設計思想を理解しよう

Page 16: MySQL5.7 GA の Multi-threaded slave

次にわたしがとった行動

- sql/rpl_rli_pdb.cc の commit log を漁る- 関連しそうな WorkLog を読む- 知らない用語が出てきたら調べる- ソースコードと MySQL5.7 が出力するバイナリログを眺めてみる

Page 17: MySQL5.7 GA の Multi-threaded slave

おおむね

わかった

Page 18: MySQL5.7 GA の Multi-threaded slave

一通り見てわかったのは

- これ初見でソースコードだけ読んで理解するのハードル高いわ

- なんで理解できなかったかわかったわ- というわけで、一つ一つ解説します

Page 19: MySQL5.7 GA の Multi-threaded slave

一つ一つ

見ていきましょう

Page 20: MySQL5.7 GA の Multi-threaded slave

はじめに

- そもそも、 slave の SQL_Thread がシングルスレッドのとき、どのようにして replication で master と同じ状態が復元されるのか?

- いたってシンプル- master が注意深く binlog 吐いてる

Page 21: MySQL5.7 GA の Multi-threaded slave

例えば InnoDB の場合

1. master で更新処理実行中の各スレッドが、それぞれ transaction cache に更新内容をためていく

2. InnoDB で PREPARE する(5.7.10 以降、 innodb_support_xa は常に true)

3. 1. の transaction cache から一連の更新処理を BEGIN&COMMIT で挟んで binlogに書く

4. InnoDBで COMMIT する

Page 22: MySQL5.7 GA の Multi-threaded slave

Two-Phase Commit & Group Commit

- MySQL の Replication 開発者であらせられる Dr. Mats Kindahl の blog この記事がわかりやすいですが- Binary Log Group Commit in MySQL 5.6

- (この後の話に関連して)大事なところを二つだけかいつまんで解説すると

Page 24: MySQL5.7 GA の Multi-threaded slave

Transaction Coordinator Log

- ソースコード中に tc_log ってのが出てきますが- Transaction の順序を管理するための Log の抽象クラスが TC_LOG であって、その実装のひとつが MYSQL_BIN_LOG

- MYSQL_BIN_LOG::prepare() や MYSQL_BIN_LOG::commit() が、 Two-Phase COMMIT を実現するために必要な関数を呼んでる

Page 25: MySQL5.7 GA の Multi-threaded slave

innodb_support_xa=true と 2PC

- innodb_support_xa=true だと、 prepare のとき undo log に xid が書き込まれる(5.7.10以降は常にそうなる)

- undo log に xid 書き込まれた PREPARED な transaction は、 クラッシュ後の再起動時、 binlog から xid 読み込んだ後、その xid 使って innobase_commit_by_xid() で最終的に COMMIT される

Page 27: MySQL5.7 GA の Multi-threaded slave

というわけで、 MySQL の 2PC は

- InnoDB のクラッシュリカバリ機能単体では実現できず、 InnoDB のクラッシュリカバリ機能と binlog のクラッシュリカバリ機能とが組み合わさって、実現されてるようです- binlog のヘッダには open するときに立てて close する

ときにリセットするフラグがあるので、正常に close した

か(クラッシュしてないか)は、フラグをみて判断してます

Page 28: MySQL5.7 GA の Multi-threaded slave

Group Commit

- Binary Log Group Commit in MySQL 5.6 の Figure.5 を参照- flush/sync/commit という stage がある- binlog へ書き出す のが flush stage- binlog に fsync() する のが sync stage- storage engine に commit するのが commit stage

- flush stage に書きだした順序で、 commit stage で commit することが保証されている

Page 29: MySQL5.7 GA の Multi-threaded slave

ソースコード的にいうと

- Group Commit はまさに MYSQL_BIN_LOG::ordered_commit()

- flush/sync/commit の stage を queue で管理することによって、 fsync() の回数を減らして、 binlog に event 書き出す順番と storage engine に commit する順番を担保している

- そして、 binlog に書くとき、各 Transaction を BEGIN - COMMIT でシリアライズしてる

Page 30: MySQL5.7 GA の Multi-threaded slave

だから binary log は読みやすいし

- そして slave の SQL_Thread は性能がでない- master は Transaction を並列実行しながらも、それらをひとかたまりの BEGIN - COMMIT にまとめシリアライズして binlog に吐いている

- master では並列実行してる Transaction が、 slave だと BEGIN - COMMIT のひとかたまりが、ひとつずつしか実行できない- まぁ SQL_Thread はシングルスレッドだしね

Page 31: MySQL5.7 GA の Multi-threaded slave

次に Anonymous_gtid_log_event

- なぜここでGTIDの話がはじまるのか?- WL#7592: GTIDs: generate Gtid_log_event

and Previous_gtids_log_event always- MySQL5.7.6 以降は、 GTID_MODE=OFF のときでも、 Anonymous_gtid_log_event を出力します

- それはなぜか- 理由は二つ

Page 32: MySQL5.7 GA の Multi-threaded slave

WL#7083 はわかる

- WL#7592いわく- Therefore, we need to generate a

per-transaction event also when GTID_MODE = OFF; this is needed e.g. for WL#7083 and WL#7165.

- WL#7083は、GTIDをオンラインで有効化するための修正らしいです。

- なるほどGTIDのためならしょうがない

Page 33: MySQL5.7 GA の Multi-threaded slave

しかし WL#7165 は

- WL#7165: MTS: Optimizing MTS scheduling by increasing the parallelization window on master

- Anonymous_gtid_log_event や Gtid_log_event には、 MTS を最適化するための、 logical timestamp が埋め込まれているそうです

Page 34: MySQL5.7 GA の Multi-threaded slave

それGTID関係ないよ!全然関係ないよ!!

Page 35: MySQL5.7 GA の Multi-threaded slave

気を取り直して logical timestamp とは

- WL#6314: MTS: Prepared transactions slave parallel applier で解説されてます

- Lamport clock を使っているようです。- (すごい雑にいうと)、 slave で並列実行可能であること示すヒントを、 master は binlog に埋め込み、 slave は binlog からヒントを読んで、複数のTransactionを並列実行するようです。

Page 36: MySQL5.7 GA の Multi-threaded slave

Lamport Clock とは

- Lamport Timestamps とも呼ばれるようです- 分散処理システムで使われているアルゴリズムのようですが、よくできていてわりとシンプルな考え方です

- 詳しくは後ほど

Page 37: MySQL5.7 GA の Multi-threaded slave

Anonymous_gtid_log_event には

- last_committed と sequence_number が 8byte ずつ埋め込まれている。これが MySQL での logical timestamp。

- sequence_number は、master で binlog に Transaction をflushする度に increment される

- last_committed は、master で commit 済みの Transaction のうち、最も値の大きい sequence_number

Page 38: MySQL5.7 GA の Multi-threaded slave

そしてAnonymous_gtid_log_eventは

- binlog に BEGIN 書きだす前に、出力されています。

- ANONYMOUS_GTID(or GTID) -> BEGIN -> (statement or row) -> COMMIT という順で書かれるわけです。

- ゆえに、後続する Transaction(BEGIN - COMMIT)に sequence_number を付与できるわけです。

Page 39: MySQL5.7 GA の Multi-threaded slave

つまるところ

- --slave-parallel-type=LOGICAL_CLOCK のとき、 GTID の log_event に埋め込まれた logical timestamp を利用している。

- slave で複数の Transaction が同時に実行されたら、それらの Transaction に紐付いた sequence_number が、(最終的に) slave の last_lwm_timestamp を更新している- lwm == low-water-mark

Page 40: MySQL5.7 GA の Multi-threaded slave

図に描くとこう

Page 41: MySQL5.7 GA の Multi-threaded slave

一つ一つ

見ていきましょう

Page 42: MySQL5.7 GA の Multi-threaded slave

last_committed

- binlog 読んだとき、 その Transaction に紐付いてる last_committed が last_lwm_timestamp より小さければ、実行可能と slave は判断する

- last_committed は、その Transaction が lock を取得するまでに、 COMMIT が完了しているべき Transaction を示す値

Page 43: MySQL5.7 GA の Multi-threaded slave

Group Assigned Queue(GAQ)

- last_lwm_timestamp は GAQ と関係している- GAQ は、 5.6 のMTSで(WL#5569)できた概念で、雑にいうと- GAQ は、Coordinator Thread が Relay Log から

binlog event 読みだして Worker Thread に 渡すとき、

管理に使う、 固定長の queue- Transaction という job の Group をどのWorker

Thread に Assign して、実行完了したかどうかを管理。

Page 44: MySQL5.7 GA の Multi-threaded slave

GAQ の checkpoint

- 具体的には mts_checkpoint_routine()- GAQ使い切るか、次のいずれかのタイミングで

- slave_checkpoint_group 回 Transaction を実行- slave_checkpoint_period msec 経過したとき

- 次のような処理をする- 実行完了した Transaction のエントリを GAQ から削除- SHOW SLAVE STATUS で表示される情報を更新- GAQ.lwm を更新。これ重要大変重要

- これが最終的に last_lwm_timestamp を更新する

Page 45: MySQL5.7 GA の Multi-threaded slave

last_lwm_timestamp の必要性

- Coordinator Thread が checkpoint で GAQ.lwm を更新する理由(推測)

- Transaction 完了した worker thread が直接 last_lwm_timstamp を更新するとマズイ

- 複数の Worker が Transaction を実行する場合、古くて時間のかかる Transaction が残ってるかもしれない

- Transaction を assign した Coordinator がときどき Worker の状態を見て、 どこまで Transaction 捌けてるか確認して lwm 更新する方が良い

Page 46: MySQL5.7 GA の Multi-threaded slave

というのが、 LOGICAL_CLOCK に

基づいた MTS

Page 47: MySQL5.7 GA の Multi-threaded slave

さしあたって

- slave-parallel-type=LOGICAL_CLOCK で性能上がるかどうかは

- master の binlog で Gtid_log_event や Anonymous_gtid_log_event の last_committed をみて、同じ last_committed がいくつあるか見ると、参考になる- 同じ last_committed の イベントが多いということは、そ

れだけ slave で同時に実行できる Transaction が多い

Page 48: MySQL5.7 GA の Multi-threaded slave

例えば

- 同じ last_committed の値を数えられるから- $ mysqlbinlog ${BINLOG_FILE} | egrep ‘GTID.*last_committed’ | awk

'{print $11}' | sort | uniq -c

- 同時実行可能な Transaction の数の上限を、ざっくり数えられる- $ mysqlbinlog ${BINLOG_FILE} | egrep

‘GTID.*last_committed’| awk '{print $11}' | sort | uniq -c | sort -n | tail

Page 49: MySQL5.7 GA の Multi-threaded slave

次に

Page 50: MySQL5.7 GA の Multi-threaded slave

- last_committed を基準に複数の worker thread が Transaction を実行していいということになると、 last_committed 的にOKなら、 InnoDB の COMMIT の順序はどうなってもいいということになる

- ということは、 slave が複数存在した場合、 slave ごとに COMMIT の順序が異なるということになる

consistency の問題

Page 51: MySQL5.7 GA の Multi-threaded slave

slave ごとに COMMIT の順が異なると

- replication が遅延してるしてないの問題ではなく

- slave ごとに異なる状態が見えてしまう- 例えば、 master で Table A, Table B という二つのTable にそれぞれ Record X, Record Yが 別々の Transaction から INSERT されたとき

- X しか見えない slave と、 Y しか見えない slave が存在しうることになる

Page 52: MySQL5.7 GA の Multi-threaded slave

slave-parallel-type=DATABASE では

- この consistency の問題を回避するすべがない

- DATABASE が複数あった場合、DATABASE間で更新順序が保証されない

- 順序が保証されなくても、最終的に整合性は保たれるだろうけど- 例えば、master で更新処理が終わったとき、すべての

slave の table は同じ状態にあるはず

Page 53: MySQL5.7 GA の Multi-threaded slave

slave-paralell-type=DATABASEのことは

Page 54: MySQL5.7 GA の Multi-threaded slave

存在自体

忘れようと

わたしは決めた

Page 55: MySQL5.7 GA の Multi-threaded slave

※感想には個人差があります

Page 56: MySQL5.7 GA の Multi-threaded slave

consistency 関連の WorkLog

- WL#6813: MTS: ordered commits (sequential consistency)

- すべての slave は master の binlog と同じ順番で COMMIT するべきだという WorkLog です

- そのためにでてくるオプションが slave_preserve_commit_order

Page 57: MySQL5.7 GA の Multi-threaded slave

slave_preserve_commit_order

- blog にもありますが制限がいくつかあります- On master

- binlog_order_commits should be enabled

- On slave- binlog_order_commits should be enabled- binary log should be enabled- log_slave_update should be enabled- slave_preserve_commit_order should be enabled

- そして LOGICAL_CLOCK 必須

Page 58: MySQL5.7 GA の Multi-threaded slave

なぜ log_slave_updates ?

- Commit_order_manager のインスタンスが生成される条件 になってるんですが

- slave で binlog を吐くときに、 Two-Phase Commit や Group Commit を使うことで、 InnoDB の COMMIT 順を制御できるから- slave で binlog の COMMIT 順を担保することで、

InnoDB の COMMIT 順を担保している

- Master の Group Commit をリプレイしてる

Page 59: MySQL5.7 GA の Multi-threaded slave

ざっくり流れとしては

1. slave の cordinator thread が relay log 読む2. cordinator thread が

Commit_order_manager::register_trx() で Commit_order_manager の FIFO な queue に worker thread の id つむ

3. worker thread が並行して Transaction 実行4. process_flush_stage_queue() で、 2. の

queue の順に binlog を書き出す(FLUSH)

Page 60: MySQL5.7 GA の Multi-threaded slave

そして

5. sync_binlog_file() で binlog を fsync() する(sync_binlog の値次第で、 fsync しないこともあるけれど)

6. process_commit_stage_queue() で InnoDB に COMMIT する

Page 61: MySQL5.7 GA の Multi-threaded slave

図に描くとこう

Page 62: MySQL5.7 GA の Multi-threaded slave

かくして

slave の COMMIT の順序は

master の binlog の順序に従って

COMMIT されるようになり

Page 63: MySQL5.7 GA の Multi-threaded slave

slave の世界に

整合性がもたらされるのだが

Page 64: MySQL5.7 GA の Multi-threaded slave

なんという

パワープレイ!

Page 65: MySQL5.7 GA の Multi-threaded slave

※感想には個人差があります

Page 66: MySQL5.7 GA の Multi-threaded slave

それから、 Slave での retry

- 5.6 のとき、松信さんが MTS でも slave_transaction_retries 有効にして欲しい とバグレポートあげておられたのですが

- WL#6964 で対応されました- slave で一時的なエラーが発生したとしても、これで自動で対応可能に- 例えば、 MTS で worker thread 起動しすぎるなどして

transaction が timeout しちゃったとしても、 retry できる

Page 67: MySQL5.7 GA の Multi-threaded slave

あと、補足すると

- MTS & Statement-Based Replication & 非決定性クエリの組み合わせはダメゼッタイ- INSERT … SELECT など、 MTS だと slave ごとに結

果が変わってもおかしくない

- MTS & READ UNCOMMITTED の組み合わせもヤバイと思う- slave_preserve_commit_order で保証されるのは、

binlog の COMMIT の順番だけなので

Page 68: MySQL5.7 GA の Multi-threaded slave

もうちょっと補足すると

- slave_pending_jobs_size_max を master のmax_allowed_packet より大きくするべき- Coordinator Thread が Worker Thread に job (binlog

event)を積むとき、slave_pending_jobs_size_max より大きな binlog event を積めないので

- どっちも default のままなら、充分な余裕があると思う

Page 69: MySQL5.7 GA の Multi-threaded slave

もっというと

- LOGICAL_CLOCK ベースの MTS は、ある程度 master が忙しくないと、効果が薄い- SQL_Thread でやってた仕事が、 cordinator thread と

worker thread で分担されるので、オーバヘッドが大きく

なる。 WL#6314 の Highe Level Architecture の 3.2 Problems にもそう書いてある

Page 70: MySQL5.7 GA の Multi-threaded slave

なにはともあれ

- おおむね実装わかったし- slave_preserve_commit_order や

log_slave_updates などを指定すれば、 master の binlog と同じ順序で MTS の slave も SQL 実行されるとわかった

Page 71: MySQL5.7 GA の Multi-threaded slave

とりあえず

- かつて slave-parallel-type=DATABASE 相当の実装しかなかったときは、 consistency の問題が厳しかった(と思う)

- それが今ではだいぶ楽になったんじゃないかなぁ。

- LOGICAL_CLOCK 使う分には

Page 72: MySQL5.7 GA の Multi-threaded slave

だがしかし

Page 73: MySQL5.7 GA の Multi-threaded slave

ここで

残念なお知らせが

あります

Page 74: MySQL5.7 GA の Multi-threaded slave

MTS使うときは

5.7でも

GTID推奨です!

Page 75: MySQL5.7 GA の Multi-threaded slave

かつて Percona の人は言いました

- MySQL5.6 で MTS 使うなら GTID 有効にしましょうと- sql_slave_skip_counter するときなどがつらいんで

- 5.7 は slave_preserve_commit_order のおかげでだいぶ良くなったんだけど

- すべてはただ一つの問題

Page 76: MySQL5.7 GA の Multi-threaded slave

MTS有効にしたときは

Exec_Master_Log_Posの意味が変わってしまう

Page 77: MySQL5.7 GA の Multi-threaded slave

Exec_Master_Log_Pos の意味

- MTS 使うとき、 relay_log_info_repository = ‘TABLE’ にして select * from mysql.slave_worker_info; するとわかる

- (worker thread が更新処理を実行しているとき、)worker thread ごとの Master_log_pos と Exec_Master_Log_Pos は一致しない。

Page 78: MySQL5.7 GA の Multi-threaded slave

SHOW SLAVE STATUS の更新頻度

- MTS のとき、 Exec_Master_Log_Pos などはリアルタイムで更新されない

- 先ほど出てきた、 GAQ の checkpoint のタイミングで、 Exec_Master_Log_Pos などが更新される

- MTS を使う場合、 SHOW SLAVE STATUS だけに頼るわけには行かなくなってくる

Page 80: MySQL5.7 GA の Multi-threaded slave

Half-applied transacitons

- SQL_Thread を KILL などしたとき、 rollback できないと、 transaction の Atomicity が保たれない

- まぁこれは InnoDB 使えばいいでしょ- MTS 有効なときでも

slave_transaction_retries 効くようになったし- MySQL 5.7 すばらしい

Page 81: MySQL5.7 GA の Multi-threaded slave

Gaps

- ざっくりいうと、 5.6 以前の MTS だと binlog の順に Transaction 実行される保証がないので、 「一時的なエラーなどで、 relay log の途中に実行されてない event が残ったらどうなるの?」という話

- これは slave_preserve_commit_order で commit 順保証できるようになって、改善した

- MySQL 5.7 すばらしい

Page 82: MySQL5.7 GA の Multi-threaded slave

Gap-free low-watermark position

- これが Exec_Master_Log_Pos の話- 5.7 で LOGICAL_CLOCK 使っても、コレが避けられない

- MTS 有効なとき、 mysql.slave_worker_info の Checkpoint_master_log_pos が、 Exec_Master_Log_Pos になる- worker_thread がどこまで relay log 上の event を実行

したかは、 Exec_Master_Log_Pos では分からない

Page 83: MySQL5.7 GA の Multi-threaded slave

そして、sql_slave_skip_counter 問題

- 特定の event だけ狙って skip するの、 MTS だとめんどくさい

- ここはやっぱ GTID 使えるほうが便利

Page 84: MySQL5.7 GA の Multi-threaded slave

かつて Yahoo! Inc. の人は言いました

- 昨年の Oracle Open World で- 「Multi-Threaded Replication 導入しつつ

GTID 入れて、GTID入れるために Percona Server 5.6 導入した」と言ってたんですが

- MySQL 5.7 になっても、 やっぱり GTID 使えるほうが、 MTS は導入しやすいママなんだなぁ

- 遺憾でござる。

Page 85: MySQL5.7 GA の Multi-threaded slave

今回、改めて思ったのは

- あるていど難しい実装になると、コード読んだだけでは新機能を理解できないこともある

- その点、 MySQL は commit log から WorkLog 漁っていけば、設計思想を踏まえて理解していくことができる

- 非常にとっつきやすいOSSで素晴らしいなと思いました

Page 86: MySQL5.7 GA の Multi-threaded slave

そして、いまやGTIDは

- GTID は master の failover をシンプルにするためだけではなく

- GTID を踏まえつつ MTS が設計されているなど、 replication の性能向上目的でも、(間接的に)使われるようになってきてる

- MySQL5.6 のとき、 Facebook さんらが GTID のバグレポートたくさんしてくれたし、そろそろ導入していったほうが良い時期かなぁ

Page 87: MySQL5.7 GA の Multi-threaded slave

ただ、 GTID まだ入れられない場合でも

- 「やっべ slave めっちゃ遅延してるどうしよう」という状況になったとき、非常手段として、一時的に LOGICAL_CLOCK & slave_preserve_commit_order & log_slave_updates という手段が取れるようになったのはけっこう便利なんじゃないでしょうか

- SET GLOBAL relay_log_info_repository = ‘TABLE’ できるから、意外と敷居高くないし

Page 88: MySQL5.7 GA の Multi-threaded slave

MTS使うときのまとめ

- LOGICAL_CLOCK がよさそう- slave-parallel-type=LOGICAL_CLOCK- slave-parallel-workers > 1- log_slave_updates=ON- slave_preserve_commit_order=ON

- mysql.slave_worker_info 見えると良い- relay_log_info_repository = ‘TABLE’

Page 89: MySQL5.7 GA の Multi-threaded slave

- max_allowed_packet いじってるなら、 slave_pending_jobs_size_max も見なおそう

- SET GLOBAL sql_slave_skip_counter =N; を運用上使いたいなら、 GTID 有効にするのが無難

Page 90: MySQL5.7 GA の Multi-threaded slave

おわり