この余⽩はタイトルを書くには狭すぎ
る
余⽩じゃなくてタイトル欄なんだけどな
2016/02/20
yoku0825
第2回 MySQL・PostgreSQLユーザーグループ合同DB勉強会 in 東京
おしながき
「明⽇使えない⾖知識」その1 (予告)
「明⽇使えない⾖知識」その2
「明⽇使えない⾖知識」その3
「明⽇使えない⾖知識」その4
「明⽇使えない⾖知識」その1 (本編)
1/133
「明⽇使えな
い⾖知識」そ
の1(予告)
2/133
NOW関数は現
在時刻を返さ
ない
3/133
真相は番組の後
半、チャンネル
はそのまま︕
4/133
「明⽇使えな
い⾖知識」そ
の2
5/133
MySQL 5.7
2013/04 MySQL 5.7.1 DMR11
2015/03 MySQL 5.7.6 DMR16
2015/04 MySQL 5.7.7 RC
2015/08 MySQL 5.7.8 RC
2015/10 MySQL ...
MySQL 5.7
2015/04 MySQL 5.7.7 RC
ここまではまあいい
2015/08 MySQL 5.7.8 RC
JSON型, virtual generated columnの拡張, InnoDB Page
Compress...
MySQL 5.7
2015/04 MySQL 5.7.7 RC
ここまではまあいい
2015/08 MySQL 5.7.8 RC
新機能!!
2015/10 MySQL 5.7.9 GA
新機能!!
2015/12 MySQL 5.7.10 ...
General
Available #
とは
9/133
「明⽇使えな
い⾖知識」そ
の3
10/133
講演のタイトル
「イルカ㌠からゾウ㌠に伝えたいMySQLのレプリケーションの
仕組み」とか話したかったんですけどかじやまさんから5.7にし
るって⾔われてるので残念ながら5.7の何かを話します(仮) と
思ったんですけどやっぱりイルカ㌠からゾウ...
意訳
12/133
MySQL 5.7の話は
もう飽きたんでレ
プリケーションの
話をします
13/133
ことのあらまし
14/133
ことのあらまし
15/133
ことのあらまし
16/133
ことのあらまし
17/133
ことのあらまし
18/133
ことのあらまし
19/133
ことのあらまし
20/133
ことのあらまし
21/133
ことのあらまし
22/133
ことのあらまし
23/133
これはレプリケー
ション でしこたま
痛い目を⾒た の先
⼈ イルカ㌠から
24/133
これからレプリケー
ション で痛い目を⾒
る でできることが増
えていくゾウ㌠へ
25/133
語らねばなる
まい(使命
感)
26/133
というわけで
「明⽇使えない
⾖知識」その4
27/133
MySQLのレプ
リケーション
について
28/133
\こんにちは/
yoku0825@とある企業のDBA
オラクれない-
ポスグれない-
マイエスキューエる-
家に帰ると
妻の夫-
せがれの⽗-
ムスメの⽗-
Twitter: @yoku0825
Blog: ⽇々の覚書
MyNA ML: ⽇本M...
MyNAステッカー
デザインは堤井さん
今⽇持ってきてます。声かけてください。
30/133
MySQL年表
< 5.0
知らない⼦ですね
5.0
2005/10〜2012/03
5.1
2008/11〜2013/12
5.5
2010/12〜2015/12
5.6
2013/02〜
5.7
31/133
レプリケーション年表
< 5.0
3.23の頃から非同期レプリケーションがあった
5.1
⾏ベースレプリケーションフォーマット追加
5.5
準同期レプリケーションの追加
5.6
GTID、レプリケーション情報のInnoDBテーブル導⼊、マルチ
...
レプリケーションの動作原理
同じデータを持ったサーバーがあって
同じSQLを同じ順番で適⽤すれば
最終的に同じデータに戻るよね︖
という期待に基づいた、結果整合性モデル
33/133
レプリケーションのご法度
スレーブに更新をかけると「同じデータを持ったサーバー」
の前提が崩れる
循環レプリケーション…だと…︖-
非決定性関数を使うと「同じSQLを同じ順番で適⽤しても」
同じデータに戻らくなるよね︖
有名どころでSYSDAT...
MySQLのレプリケーションアーキテクチャー
clientA
connection executor storage_engine
binlog binlog_dump
io_thread relaylog
slave_executorsql_...
MySQLレプリケーション⽤語
バイナリーログ, binlog
リレーログ
Binlog Dump Thread
I/Oスレッド, Receiver Thread
SQLスレッド, Applier Thread
36/133
MySQLのレプリケーションアーキテクチャー
Executorがストレージエンジンに書く1.
Executorがバイナリーログに書く2.
Binlog Dump Threadがバイナリーログを読む3.
I/O ThreadがBinlog Dum...
MySQLのレプリケーションアーキテクチャー
Executorがストレージエンジンに書く1.
Executorがバイナリーログに書く2.
Binlog Dump Threadがバイナリーログを読む3.
I/O ThreadがBinlog Dum...
Executorがストレージエンジンに書く
もちろんトランザクション対応はストレージエンジン依存
5.6まではコミットの時点でストレージエンジンのコミット
をしてしまっていた
5.7からはこの時点ではまだコミット されない
39/133
MySQLのレプリケーションアーキテクチャー
Executorがストレージエンジンに書く1.
Executorがバイナリーログに書く2.
Binlog Dump Threadがバイナリーログを読む3.
I/O ThreadがBinlog Dum...
Executorがバイナリーログに書く
Executorから⾒たバイナリーログは binlogストレージエン
ジン
MySQLにもともと実装されているXAトランザクションを使
って⼆相コミット
binlog̲cacheにXA PREPAREして...
ストレージエンジンとして⾒たbinlog
A
binlog_cacheとsync_binlogによりアトミックっぽく振る舞え
るけど厳密にAtomicじゃない
C
ストレージエンジン層がコミットをシリアライズしてくれるこ
とに依存
I
常にSE...
バイナリーログのその他の使い道
PITR
シリアライズされた更新情報なのでPITRに使う-
SQLをパースして⾊々する
テーブルごとのUPDATE回数を後追いで集計するとか-
中⾝を取り出して別のデータストアに⼊れるとか-
43/133
MySQLのレプリケーションアーキテクチャー
Executorがストレージエンジンに書く1.
Executorがバイナリーログに書く2.
Binlog Dump Threadがバイナリーログを読む3.
I/O ThreadがBinlog Dum...
Binlog Dump Threadがバイナリーログを読む
fsyncしててもしてなくてもwriteされた時点から読める
マスターのmysqldではクライアントからのコネクション扱
い
スレーブでSTART SLAVE => マスターで認証 =...
MySQLのレプリケーションアーキテクチャー
Executorがストレージエンジンに書く1.
Executorがバイナリーログに書く2.
Binlog Dump Threadがバイナリーログを読む3.
I/O ThreadがBinlog Dum...
I/O ThreadがBinlog Dumpからイベントを受け取って
リレーログに書く
ここからスレーブのmysqld
Binlog Dumpから送り付けられたイベントをリレーログと
して書き込む
ちなみに、mysqlbinlog -Rも(マス...
MySQLのレプリケーションアーキテクチャー
Executorがストレージエンジンに書く1.
Executorがバイナリーログに書く2.
Binlog Dump Threadがバイナリーログを読む3.
I/O ThreadがBinlog Dum...
SQL Threadがリレーログからイベントを読み取って⾃⾝
のExecutorを叩く
これによりマスターのExecutorがまるでスレーブの
Executorも叩いたかの様にデータが更新される
Executorはまたバイナリーログを吐くことも...
binlogフォーマット
SBR
Statement Based Replication
RBR
Row Based Replication
MBR(あんまり⾔わない)
Mixed Based Replication
50/133
SBR
いわゆる MySQLのレプリケーション っぽいやつ
binlogに記録されるのはエンコードされた SQLステートメ
ント
イベントはステートメント単位-
MySQL 5.6とそれ以前のデフォルト
51/133
SBR
$ mysqlbinlog -R -h 127.0.0.1 -P 64057 -uroot --stop-never bin.00
0010
mysql57> SET SESSION binlog_format= 'STATEMENT'...
SBR
SQLステートメントが記録されるため、そのステートメント
が何百万⾏更新しようと1ステートメントぶんのスペースし
か取らない。
容量的なワーストケースはINSERTや1⾏UPDATE。-
SQLとしてパースされるため、「マスターには存在...
SBR
SQLとしてそれぞれのサーバーで実⾏されるため、非決定性
(実⾏するたびに結果が違う)ステートメントを使うと死
ぬ。
http://dev.mysql.com/doc/refman/5.6/ja/
replication-rbr-saf...
READ-COMMITTEDがSBRを壊す︖
REPEATABLE-READならネクストキーロックでtrx2がブロ
ックされる。
+-----+------+
| num | val |
+-----+------+
| 1 | one |
+...
RBR
5.1から導⼊
binlogに記録されるのは⾏の変更前の値と変更後の値をバイ
ナリーエンコードしたもの
イベントは⾏単位-
ただしDDLは設定に関わらずSBRで記録される
MySQL 5.7からのデフォルト
56/133
RBR
$ mysqlbinlog -R -h 127.0.0.1 -P 64057 -uroot --stop-never bin.000010
mysql57> SET SESSION binlog_format= 'ROW';
Query...
RBR
1⾏1イベント。100万⾏更新すると死ぬ。
INSERTや1⾏UPDATEならSBRとそんなに容量変わらな
い。
-
スレーブでも⾏探索と更新は⾏われるので、 プライマリ
ーキーが無いとカジュアルに死ぬ
-
「マスターには存在したけどス...
RBR
非決定性関数だろうと「実⾏結果が記録」されるため、マス
ターとスレーブでも値はズレない。
マスターでのみトリガーが解釈され、トリガー元テーブルと
トリガー先テーブルの両⽅のイベントがbinlogに記録され
る。
マスターとスレーブでトリ...
MBR
基本はSBR、非決定性ステートメントだけRBRで使い分け
る。MBRと呼ぶのは稀。
いいとこ尽くしに聞こえなくもないけど、実際は思わぬとこ
ろでRBRにフォールバックして割とカジュアルに死ぬ。
マスタースレーブでトリガーをズラして調整し...
初⼼者は黙ってRBR(5.7ʼs default)
初⼼者は黙ってRBR
サイレントにデータがズレるよりはエラって⽌まった⽅がマ
シ
データのズレを検出&リカバリーするにはpt-table-
checksumとpt-table-syncが有効
...
pt-table-checksum
SBRとRBRでそれぞれチェックサムを計算してテーブルに突
っ込むクエリーを発⾏
マスター上では当然SBRでもRBRでも同じチェックサム
になる
-
スレーブではSBRで来たイベントは スレーブでチェックサ
...
pt-online-schema-change
変更元テーブルをコピーして先にALTER TABLEを適⽤する
変更元テーブルにトリガーを仕掛けて、変更元テーブルに対
する更新がコピーしたテーブルにも反映されるようにする
READ-COMMIT...
pt-online-schema-change
InnoDBオンラインDDLが導⼊された5.6以降でも有効
何故なら、SQLスレッドは相変わらず1本(あるいは、同じ
テーブルだとMTS使ってても追い越せない)ので、ALTER
TABLEに時間が...
バイナリーログの⼀⽣
マスター上でコミットされた順にbinlogにエンコード
binlogからrelaylogにシングルスレッドで転送(順序は保証
される)
relaylogはシングルスレッドまたはマルチスレッドで適⽤
MySQL 5.5とそれ...
MTSのアーキテクチャー
clientA
connection executor storage_engine
binlog binlog_dump
io_thread relaylog
slave_executor1
slave_execut...
MTSのアーキテクチャー
マスターのバイナリーログがリレーログに記録されるところ
までは⼀緒
1.
SQL Thread(coordinator)がリレーログからイベントを取
り出す
2.
coordinatorがslave̲worker̲th...
MTSのアーキテクチャー
マスターのバイナリーログがリレーログに記録されるところ
までは⼀緒
1.
SQL Thread(coordinator)がリレーログからイベントを取
り出す
2.
coordinatorがslave̲worker̲th...
MTSコーディネーター
前後のイベントが互いに⼲渉しない(順序を⼊れ替えても問
題ない)かどうかの責任を持つ
ただし順序が⼊れ替わる(線形でない)ことが⼤前提の
ため、シングルスレッドレプリケーションよりも結果整
合性の⾊が強い
-
69/133
MTSコーディネーター
MySQL 5.6ではスキーマが分かれていることで⼲渉しない
ことを担保(5.7のslave_parallel_type= DATABASE相当)
5.7ではマスターでbinlogに記録された時の直前のコミット
のタイム...
MTSのアーキテクチャー
マスターのバイナリーログがリレーログに記録されるところ
までは⼀緒
1.
SQL Thread(coordinator)がリレーログからイベントを取
り出す
2.
coordinatorがslave̲worker̲th...
slave̲worker̲thread
独⽴して動作するため、RR(Repeatable-Read)でもマス
ターと同⼀のデータベース全体のスナップショットを保証で
きない
5.6ではスレーブ側のバイナリーログの中⾝は順序を保証で
きない(5....
イベントの識別
たとえばInnoDBログならLSN
バイナリーログはファイル名とファイルの先頭からのオフセ
ットバイト数
これらはマスター上でのみ⼀意に識別されるものなので
カスケードすると変わる
-
MySQL 5.6とそれ以降のGTIDもこ...
CHANGE MASTER TO
mysql> CHANGE MASTER TO master_log_file= '..', master_log_pos
= ..;
このバイナリーログのこのポジションから先を寄越せ、とい
うクライアントから...
master.info
マスターの情報を保持するための構造。コード追う時は
mi。
CHANGE MASTER TOで与えられた情報 + αが⼊ってる。
relay_log_recovery != 1の時はここからファイルとポジシ
ョンの情報を...
master.info
slave1 [localhost] {msandbox} ((none)) > SELECT * FROM mysql.slave_master_infoG
*************************** 1....
relay̲log.info
リレーログ(SQLスレッド, slave̲worker̲thread)の情報
を保持するための構造。コード追う時はrli。
Relay̲log̲fileとかRelay̲log̲posとか
Relay̲Master̲...
relay̲log.info
slave1 [localhost] {msandbox} ((none)) > SELECT * FROM mysql.slav
e_relay_log_infoG
***********************...
レプリケーションとマスタークラッシュ
バイナリーログ マスターストレージ リレーログ 影響
残ってない 未更新 受信してない なし(︖)
残ってない 未更新 受信した データ不整合(スレーブに
あってマスターにない)
しかもエラー
(ER̲MA...
レプリケーションとマスタークラッシュ
sync_binlog= 1だと起こり得る範囲がぐっと狭く
バイナリーログ マスターストレージ リレーログ 影響
残ってる 未更新 受信してない トランザクションロ
スト
残ってる 未更新 受信した データ...
レプリケーションとマスタークラッシュ
またはsemisync + log_slave_updatesでマスター切り替え
バイナリーログ マスターストレージ リレーログ 影響
残ってない 未更新 受信した データ不整合(スレーブに
あってマスター...
レプリケーションとスレーブクラッシュ
リレーログ master.info SQLスレッド relay̲log.info 影響
受け取ってない 記録してない 適⽤してない 記録してない なし
受け取ってる 記録してない 適⽤してない 記録してない...
レプリケーションとスレーブクラッシュ
relay_log_info_repository= TABLE
ただしInnoDB前提(innodb_flush_log_at_trx_commit
= 1で次の表)
-
SQLスレッドのイベント適⽤と
...
relay_log_info_repository= TABLE &&
innodb_flush_log_at_trx_commit = 1
リレーログ master.info SQLスレッド relay̲log.info 影響
受け取ってない...
レプリケーションとスレーブクラッシュ
relay_log_recovery
レプリケーションの再開時にmaster.infoのポジション情
報をアテにせず、relaylog.infoの情報を元にレプリケー
ションを復元する
-
受信済みだけど未...
relay_log_recovery
リレーログ master.info SQLスレッド relay̲log.info 影響
受け取ってない 記録してない 適⽤してない 記録してない なし
受け取ってる 記録してない 適⽤した 記録してない リ...
レプリケーションとスレーブクラッシュ
男らしくバックアップからリストアする
割と真⾯目に。
毎回リストアすると割り切れば、ACIDのDは無茶な⽅向
に振れて性能が稼げるお( ^ω^)
-
87/133
レプリケーションとスレーブクラッシュ
sync̲relay̲log?
syncされていようとsyncされていまいと、リレーログからレ
プリケーション再開位置を特定するわけではない
sync̲master̲info?
relay_log_reco...
マスター側のフィルターに関するパラメーター
server_id, replicate_same_server_id
フィルター関連っぽくないけど。-
⾃分と同じサーバーIDのイベントは読み⾶ばす
カスケードすると同じサーバーIDのmysqldが...
スレーブ側のフィルターに関するパラメーター
SQLスレッドでフィルター
なので、I/Oスレッドはフツーに受信してリレーログまで
吐く
-
replicate_do_db, replicate_ignore_db-
replicate_do_ta...
レプリケーションフィルターの評価順
フローチャートになってるので⾒やすい
MySQL :: MySQL 5.6 リファレンスマニュアル :: 17.2.3
サーバーがレプリケーションフィルタリングルールをどのよ
うに評価するか
マスターとスレー...
レプリケーションで垂直シャード
table1 table2 table3
binlog
replicate_do_table= t
able1
table1 replicate_do_table= t
able2, table3
table2
...
マスターとスレーブで
バージョンが違ってもいい(レプリケーションがサポートさ
れるのは原則リリース系列1世代)
スレーブを先にバージョンアップするパターンのみ
全部のスレーブを先にバージョンアップしてマスター切り替
えして、旧マスターをバージョ...
マスターとスレーブで
ストレージエンジンが違ってもいい(だがマスターを
BLACKHOLEはやめておけ)
マスターはInnoDBでトランザクション保護、集計⽤スレー
ブはMyISAMでスキャンしまくる遊び(あるいは、MyISAM
は容量効率がい...
マスターとスレーブで
インデックスがあったりなかったりしていい(カラムはやめ
ておいた⽅が無難)
RSU(Rolling Schema Update)って呼ぶこともある。
呼ばないこともある。
-
5.6のInnoDBオンラインDDLでRSUが...
これまでのレプリケーションの制約
I/Oスレッド - リレーログ - SQLスレッド で1組
5.6からSQLスレッドは並列化可能に-
I/Oスレッドが1本しかないということは、「スレーブか
ら⾒たマスターは1つしか存在できない」
マスターから...
複数のマスターを持ちたい理由
集計⽤スレーブ
あっちのサーバーのデータとこっちのサーバーのデータ
をJOINしたい
-
集計⽤と割り切ればHDDのRAID5で容量を稼ぐという選
択肢もありだし
-
シャードの集約
複数のシャードをまとめてサーバ...
N対1レプリケーション
通称えぬいちレプリケーションまたはどあきレプリケー
ション
「1つのマスターしか設定できないなら、定期的にマスター
を切り替えればいいじゃない」
do-aki/N1Repl: master n : slave 1 rep...
N対1レプリケーション
master1 slave master2
START SLAVE
Binlog Dump
Applying
CHANGE MASTER TO
Binlog Dump
Applying
CHANGE MASTER TO
...
N対1レプリケーション
実はMySQL Utilitiesにもmysqlrplmsというどあきレプリケ
ーションスクリプトがある
ただしこちらはGTID必須
mysqlrplms ̶ Set Up and Start Replication A...
(Native) Multi Source Replication
MySQLでは5.7、MariaDBでは10.0から
「1つのI/Oスレッドが1つのマスターしか設定できないな
ら、I/Oスレッドごと横に増やせばいいじゃない」
I/Oスレッド...
(Native) Multi Source Replication
master1 slave_channel_1 slave_channel_2 master2
START SLAVE FOR CHANNE
L 1
Binlog Dump
A...
お⼿軽シャード集約
スキーマが分かれている場合
インポートだけ間違えなければ⼤丈夫
スキーマは同じだけどテーブルが分かれている場合
インポートだけ間違えなければ⼀応⼤丈夫
同じ名前空間のテーブルがある
ユニークキーは本当にユニーク︖ サロゲート...
GTID
Global Transaction IDentifier
サーバー識別⼦(マスターの@@server_uuid)、ソースを
追っかけるならSIDNO(Source ID NO)
datadir/auto.cnfに保管されるので、リス...
GTIDとマスター
バイナリーログにGTIDを埋め込むようになる…くらいしか
違いはない
とはいえgtid_mode= ONにはenforce_gtid_consistency= ON
が必要なので、マスターの振る舞いとしては違いは少なくと
も...
GTIDとI/Oスレッド
master_auto_position= 1の場合、「このファイルのこのポ
ジションから寄越せ︕」の代わりに、「この(=スレーブが
既に適⽤済みの)GTID 以外 のバイナリーログを頼む」に
なる
サーバー側が動的に...
gtid̲executedの保管
バージョン log̲bin 保存先 再起動時の
gtid̲executedの復元
5.6 OFF N/A N/A(GTIDが有効化
できない)
5.6 ON バイナリーログ 最新のバイナリーロ
グの
Previ...
gtid̲executedの保管
バージョン log̲bin 保存先 再起動時の
gtid̲executedの復元
5.7 OFF mysql.gtid̲excute
d
テーブルから
(COMMITのたびに
mysql.gtid̲execut...
GTIDとSQLスレッド
GTIDの連番部分(GNO)は気にしない
これから実⾏するトランザクションのGTID(gtid_next)が
実⾏済み(gtid_executedに含まれる)の場合、実⾏しない
(スキップする)
これによってスレーブク...
GTIDの有効化
masterslave OFF OFF̲PERMISSIVE ON̲PERMISSIVE ON
OFF ○ ○ ○ ×
OFF̲PERMIS
SIVE
○ ○ ○ ×
ON̲PERMISS
IVE
× ○ ○ ○
ON × ○...
GTIDの有効化
OFF
GTIDを振らない。GTIDの振られたイベントが来るとエラる
OFF̲PERMISSIVE (5.7から)
GTIDを振らないけど、GTIDの振られたイベントが来ても⽂句
を⾔わない
ON̲PERMISSIVE (5....
準同期レプリケーション
通称semisync
ここを同期にする
Executorがストレージエンジンに書くa.
Executorがバイナリーログに書くb.
Binlog Dump Threadがバイナリーログを読むc.
I/O ThreadがB...
準同期レプリケーションのパラメーター
rpl_semi_sync_master_timeout
デフォルトが10000(ミリ秒、つまり10秒)と⼤きい-
rpl_semi_sync_master_wait_no_slave
OFFにすると、スレ...
準同期レプリケーションの拡張 at 5.7
rpl_semi_sync_master_wait_for_slave_count
いくつのI/O ThreadがACKを返したらマスター上でOKと
されるかを指定可能に
-
rpl_semi_syn...
その他のレプ
リケーショ
ン︖
115/133
仮想完全同期レプリケーション
通称Galera Cluster
本家codershipのGalera Cluster for MySQL, Percona実
装のPercona XtraDB Cluster, MariaDB実装のMariaDB...
Galera Cluster
ローカルノードにトランザクションを展開1.
COMMIT前にGalera Cacheに書き込み2.
Galera Cacheのプロパゲート3.
他ノードからACK4.
ローカルノードでCOMMIT完了5.
他ノード...
Percona XtraBackup
レプリケーション︖
グローバルロックをかけてLSNを取り出すa.
テーブルスペースファイルのコピーb.
コピー中、InnoDBログをスキャンして、開始時以降の
LSNのログを全て記録する
c.
コピーしたテ...
mysqlbinlog -R –stop-never –raw
マスターから⾒るとI/Oスレッドに⾒えるmysqlbinlog -Rに
バイナリーログの末尾まで⾏っても終了しない--stop-never
オプションを付け
binlogデコードを...
Facebook MySQLのmysqlbinlog
semisyncスレーブになれるようなオプションが拡張されて
る
マスターとスレーブは複数の違うDCに配置されてるらしく
て
マスターと同じDCにバイナリーログ保管⽤のmysqlbinlog...
Binlog Events
I/Oスレッド相当の実装とbinlogデコーダーの実装ライブラ
リー
地雷が埋まってるらしい。-
MySQL Binlog Events でストリーム処理してみた
#MySQLUC15
-
Labs にある”Hado...
InnoDB Memcached Plugin
122/133
InnoDB Memcached Plugin
innodb_api_enable_binlogを有効にするとbinlog吐ける
イベントは全てRBR
がんばれば「トランザクション対応永続化分散
memcached」が出来るかも知れない
inn...
さあみなさん
お待ちかね
124/133
「NOW関数は現
在時刻を返さな
い」の謎に迫る
125/133
NOW関数
NOW() は、ステートメントが実⾏を開始する時刻を⽰
す定数時間を返します。
さらに、SET TIMESTAMP ステートメントによっ
て、 ..snip.. タイムスタンプをゼロ以外の値に設定する
と、後続の NOW() が起動...
NOW関数
mysql56> SELECT NOW();
2016-02-18 19:37:18
mysql56> SELECT NOW();
2016-02-18 19:37:19
mysql56> SET timestamp= 145579...
NOW関数とバイナリーログ
安全でないと⾒なされない非決定的関数。 これらの関
数は決定的ではありませんが、ロギングおよびレプリケ
ー シ ョ ン目 的の場 合は安 全と し て処 理さ れ ま す:
CONNECTION̲ID()、CURDA...
NOW関数とバイナリーログ
# at 4381
#160212 17:23:20 server id 1056 end_log_pos 4466 Query thread_i
d=43 exec_time=0 error_code=0
SET ...
レプリケーション
でしこたま痛い目
を⾒た の先⼈ イル
カ㌠から
130/133
これからレプリケー
ション で痛い目を⾒
る でできることが増
えていくゾウ㌠へ
131/133
楽しい
よ︕︕1
132/133
Questions
and/or
Suggestions?
133/133
Upcoming SlideShare
Loading in …5
×

イルカさんチームからゾウさんチームに教えたいMySQLレプリケーション

0
-1

Published on

2016/02/20 第2回 MySQL・PostgreSQLユーザーグループ(MyNA・JPUG)合同DB勉強会 in 東京

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
0
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
4
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

イルカさんチームからゾウさんチームに教えたいMySQLレプリケーション

  1. 1. この余⽩はタイトルを書くには狭すぎ る 余⽩じゃなくてタイトル欄なんだけどな 2016/02/20 yoku0825 第2回 MySQL・PostgreSQLユーザーグループ合同DB勉強会 in 東京
  2. 2. おしながき 「明⽇使えない⾖知識」その1 (予告) 「明⽇使えない⾖知識」その2 「明⽇使えない⾖知識」その3 「明⽇使えない⾖知識」その4 「明⽇使えない⾖知識」その1 (本編) 1/133
  3. 3. 「明⽇使えな い⾖知識」そ の1(予告) 2/133
  4. 4. NOW関数は現 在時刻を返さ ない 3/133
  5. 5. 真相は番組の後 半、チャンネル はそのまま︕ 4/133
  6. 6. 「明⽇使えな い⾖知識」そ の2 5/133
  7. 7. MySQL 5.7 2013/04 MySQL 5.7.1 DMR11 2015/03 MySQL 5.7.6 DMR16 2015/04 MySQL 5.7.7 RC 2015/08 MySQL 5.7.8 RC 2015/10 MySQL 5.7.9 GA 2015/12 MySQL 5.7.10 GA 2016/02 MySQL 5.7.11 GA 6/133
  8. 8. MySQL 5.7 2015/04 MySQL 5.7.7 RC ここまではまあいい 2015/08 MySQL 5.7.8 RC JSON型, virtual generated columnの拡張, InnoDB Page Compression 2015/10 MySQL 5.7.9 GA innodb_default_row_format, JSON -> operator, innodb_numa_interleave 2015/12 MySQL 5.7.10 GA Bug Fix 2016/02 MySQL 5.7.11 GA InnoDB Tablespace Encryption 7/133
  9. 9. MySQL 5.7 2015/04 MySQL 5.7.7 RC ここまではまあいい 2015/08 MySQL 5.7.8 RC 新機能!! 2015/10 MySQL 5.7.9 GA 新機能!! 2015/12 MySQL 5.7.10 GA Bug Fix 2016/02 MySQL 5.7.11 GA 新機能!! 8/133
  10. 10. General Available # とは 9/133
  11. 11. 「明⽇使えな い⾖知識」そ の3 10/133
  12. 12. 講演のタイトル 「イルカ㌠からゾウ㌠に伝えたいMySQLのレプリケーションの 仕組み」とか話したかったんですけどかじやまさんから5.7にし るって⾔われてるので残念ながら5.7の何かを話します(仮) と 思ったんですけどやっぱりイルカ㌠からゾウ㌠に伝えたい MySQLレプリケーションの話をします 11/133
  13. 13. 意訳 12/133
  14. 14. MySQL 5.7の話は もう飽きたんでレ プリケーションの 話をします 13/133
  15. 15. ことのあらまし 14/133
  16. 16. ことのあらまし 15/133
  17. 17. ことのあらまし 16/133
  18. 18. ことのあらまし 17/133
  19. 19. ことのあらまし 18/133
  20. 20. ことのあらまし 19/133
  21. 21. ことのあらまし 20/133
  22. 22. ことのあらまし 21/133
  23. 23. ことのあらまし 22/133
  24. 24. ことのあらまし 23/133
  25. 25. これはレプリケー ション でしこたま 痛い目を⾒た の先 ⼈ イルカ㌠から 24/133
  26. 26. これからレプリケー ション で痛い目を⾒ る でできることが増 えていくゾウ㌠へ 25/133
  27. 27. 語らねばなる まい(使命 感) 26/133
  28. 28. というわけで 「明⽇使えない ⾖知識」その4 27/133
  29. 29. MySQLのレプ リケーション について 28/133
  30. 30. \こんにちは/ yoku0825@とある企業のDBA オラクれない- ポスグれない- マイエスキューエる- 家に帰ると 妻の夫- せがれの⽗- ムスメの⽗- Twitter: @yoku0825 Blog: ⽇々の覚書 MyNA ML: ⽇本MySQLユーザ会 29/133
  31. 31. MyNAステッカー デザインは堤井さん 今⽇持ってきてます。声かけてください。 30/133
  32. 32. MySQL年表 < 5.0 知らない⼦ですね 5.0 2005/10〜2012/03 5.1 2008/11〜2013/12 5.5 2010/12〜2015/12 5.6 2013/02〜 5.7 31/133
  33. 33. レプリケーション年表 < 5.0 3.23の頃から非同期レプリケーションがあった 5.1 ⾏ベースレプリケーションフォーマット追加 5.5 準同期レプリケーションの追加 5.6 GTID、レプリケーション情報のInnoDBテーブル導⼊、マルチ スレッドスレーブ(MTS)の追加、binlogのグループコミット 5.7 MTSの機能強化、グループコミットの機能強化、ロスレス準同 期レプリケーション 32/133
  34. 34. レプリケーションの動作原理 同じデータを持ったサーバーがあって 同じSQLを同じ順番で適⽤すれば 最終的に同じデータに戻るよね︖ という期待に基づいた、結果整合性モデル 33/133
  35. 35. レプリケーションのご法度 スレーブに更新をかけると「同じデータを持ったサーバー」 の前提が崩れる 循環レプリケーション…だと…︖- 非決定性関数を使うと「同じSQLを同じ順番で適⽤しても」 同じデータに戻らくなるよね︖ 有名どころでSYSDATE, ユニークキーでORDER BYして ないLIMIT - 34/133
  36. 36. MySQLのレプリケーションアーキテクチャー clientA connection executor storage_engine binlog binlog_dump io_thread relaylog slave_executorsql_thread binlog storage_engine slave_connection clientB master slave 35/133
  37. 37. MySQLレプリケーション⽤語 バイナリーログ, binlog リレーログ Binlog Dump Thread I/Oスレッド, Receiver Thread SQLスレッド, Applier Thread 36/133
  38. 38. MySQLのレプリケーションアーキテクチャー Executorがストレージエンジンに書く1. Executorがバイナリーログに書く2. Binlog Dump Threadがバイナリーログを読む3. I/O ThreadがBinlog Dumpからイベントを受け取ってリレ ーログに書く 4. SQL Threadがリレーログからイベントを読み取って⾃⾝の Executorを叩く 5. 37/133
  39. 39. MySQLのレプリケーションアーキテクチャー Executorがストレージエンジンに書く1. Executorがバイナリーログに書く2. Binlog Dump Threadがバイナリーログを読む3. I/O ThreadがBinlog Dumpからイベントを受け取ってリレ ーログに書く 4. SQL Threadがリレーログからイベントを読み取って⾃⾝の Executorを叩く 5. 38/133
  40. 40. Executorがストレージエンジンに書く もちろんトランザクション対応はストレージエンジン依存 5.6まではコミットの時点でストレージエンジンのコミット をしてしまっていた 5.7からはこの時点ではまだコミット されない 39/133
  41. 41. MySQLのレプリケーションアーキテクチャー Executorがストレージエンジンに書く1. Executorがバイナリーログに書く2. Binlog Dump Threadがバイナリーログを読む3. I/O ThreadがBinlog Dumpからイベントを受け取ってリレ ーログに書く 4. SQL Threadがリレーログからイベントを読み取って⾃⾝の Executorを叩く 5. 40/133
  42. 42. Executorがバイナリーログに書く Executorから⾒たバイナリーログは binlogストレージエン ジン MySQLにもともと実装されているXAトランザクションを使 って⼆相コミット binlog̲cacheにXA PREPAREしておいてXA COMMIT- クラッシュしてもXA RECOVERはできない><- 41/133
  43. 43. ストレージエンジンとして⾒たbinlog A binlog_cacheとsync_binlogによりアトミックっぽく振る舞え るけど厳密にAtomicじゃない C ストレージエンジン層がコミットをシリアライズしてくれるこ とに依存 I 常にSERIALIZABLE D sync_binlog= 1なら⼀応Durable 42/133
  44. 44. バイナリーログのその他の使い道 PITR シリアライズされた更新情報なのでPITRに使う- SQLをパースして⾊々する テーブルごとのUPDATE回数を後追いで集計するとか- 中⾝を取り出して別のデータストアに⼊れるとか- 43/133
  45. 45. MySQLのレプリケーションアーキテクチャー Executorがストレージエンジンに書く1. Executorがバイナリーログに書く2. Binlog Dump Threadがバイナリーログを読む3. I/O ThreadがBinlog Dumpからイベントを受け取ってリレ ーログに書く 4. SQL Threadがリレーログからイベントを読み取って⾃⾝の Executorを叩く 5. 44/133
  46. 46. Binlog Dump Threadがバイナリーログを読む fsyncしててもしてなくてもwriteされた時点から読める マスターのmysqldではクライアントからのコネクション扱 い スレーブでSTART SLAVE => マスターで認証 => ESTABLISH後はマスター側からsendtoできる - 45/133
  47. 47. MySQLのレプリケーションアーキテクチャー Executorがストレージエンジンに書く1. Executorがバイナリーログに書く2. Binlog Dump Threadがバイナリーログを読む3. I/O ThreadがBinlog Dumpからイベントを受け取ってリ レーログに書く 4. SQL Threadがリレーログからイベントを読み取って⾃⾝の Executorを叩く 5. 46/133
  48. 48. I/O ThreadがBinlog Dumpからイベントを受け取って リレーログに書く ここからスレーブのmysqld Binlog Dumpから送り付けられたイベントをリレーログと して書き込む ちなみに、mysqlbinlog -Rも(マスターから⾒ると)I/Oス レッドと同じ様に振る舞う 47/133
  49. 49. MySQLのレプリケーションアーキテクチャー Executorがストレージエンジンに書く1. Executorがバイナリーログに書く2. Binlog Dump Threadがバイナリーログを読む3. I/O ThreadがBinlog Dumpからイベントを受け取ってリレ ーログに書く 4. SQL Threadがリレーログからイベントを読み取って⾃⾝ のExecutorを叩く 5. 48/133
  50. 50. SQL Threadがリレーログからイベントを読み取って⾃⾝ のExecutorを叩く これによりマスターのExecutorがまるでスレーブの Executorも叩いたかの様にデータが更新される Executorはまたバイナリーログを吐くこともできる 49/133
  51. 51. binlogフォーマット SBR Statement Based Replication RBR Row Based Replication MBR(あんまり⾔わない) Mixed Based Replication 50/133
  52. 52. SBR いわゆる MySQLのレプリケーション っぽいやつ binlogに記録されるのはエンコードされた SQLステートメ ント イベントはステートメント単位- MySQL 5.6とそれ以前のデフォルト 51/133
  53. 53. SBR $ mysqlbinlog -R -h 127.0.0.1 -P 64057 -uroot --stop-never bin.00 0010 mysql57> SET SESSION binlog_format= 'STATEMENT'; Query OK, 0 rows affected (0.00 sec) mysql57> INSERT INTO t1 VALUES (1, 'one'); Query OK, 1 row affected (0.01 sec) # at 2339 #160201 19:14:40 server id 1057 end_log_pos 2441 CRC32 0xb0e9add 8 Query thread_id=12 exec_time=0 error_code=0 SET TIMESTAMP=1454321680/*!*/; INSERT INTO t1 VALUES (1, 'one') /*!*/; 52/133
  54. 54. SBR SQLステートメントが記録されるため、そのステートメント が何百万⾏更新しようと1ステートメントぶんのスペースし か取らない。 容量的なワーストケースはINSERTや1⾏UPDATE。- SQLとしてパースされるため、「マスターには存在したけど スレーブには存在しない⾏」へのクエリーはナチュラルに無 視される(WHERE句で空振りしたクエリーはエラーじゃな くて空の結果セットを返す) 53/133
  55. 55. SBR SQLとしてそれぞれのサーバーで実⾏されるため、非決定性 (実⾏するたびに結果が違う)ステートメントを使うと死 ぬ。 http://dev.mysql.com/doc/refman/5.6/ja/ replication-rbr-safe-unsafe.html - トリガーはマスターとスレーブで個々に実⾏される(記録さ れるイベントはトリガー元テーブルに対するもののみ) READ-COMMITTEDだとマスター/スレーブでデータ不整合 を起こすのでエラーになる。 54/133
  56. 56. READ-COMMITTEDがSBRを壊す︖ REPEATABLE-READならネクストキーロックでtrx2がブロ ックされる。 +-----+------+ | num | val | +-----+------+ | 1 | one | +-----+------+ trx1> BEGIN; trx1> UPDATE t1 SET val= 'updated' WHERE num= 2; -- No row update d. trx2> BEGIN; trx2> UPDATE t1 SET num= 2 WHERE num = 1; trx2> COMMIT; trx1> COMMIT; 55/133
  57. 57. RBR 5.1から導⼊ binlogに記録されるのは⾏の変更前の値と変更後の値をバイ ナリーエンコードしたもの イベントは⾏単位- ただしDDLは設定に関わらずSBRで記録される MySQL 5.7からのデフォルト 56/133
  58. 58. RBR $ mysqlbinlog -R -h 127.0.0.1 -P 64057 -uroot --stop-never bin.000010 mysql57> SET SESSION binlog_format= 'ROW'; Query OK, 0 rows affected (0.00 sec) mysql57> INSERT INTO t1 VALUES (2, 'two'); Query OK, 1 row affected (0.00 sec) # at 2607 #160201 19:23:58 server id 1057 end_log_pos 2653 CRC32 0x424bf80 5 Table_map: `d1`.`t1` mapped to number 108 # at 2653 #160201 19:23:58 server id 1057 end_log_pos 2701 CRC32 0xf946a87 6 Write_rows: table id 108 flags: STMT_END_F BINLOG ' PjKvVhMhBAAALgAAAF0KAAAAAGwAAAAAAAEAAmQxAAJ0MQACCA8CgAACBfhLQg== PjKvVh4hBAAAMAAAAI0KAAAAAGwAAAAAAAEAAgAC//wCAAAAAAAAAAN0d292qEb5 '/*!*/; 57/133
  59. 59. RBR 1⾏1イベント。100万⾏更新すると死ぬ。 INSERTや1⾏UPDATEならSBRとそんなに容量変わらな い。 - スレーブでも⾏探索と更新は⾏われるので、 プライマリ ーキーが無いとカジュアルに死ぬ - 「マスターには存在したけどスレーブには存在しない⾏」へ のクエリーはエラーで⽌まる(更新前の値を持つ⾏が⾒付か らないとER̲KEY̲NOT̲FOUND) 58/133
  60. 60. RBR 非決定性関数だろうと「実⾏結果が記録」されるため、マス ターとスレーブでも値はズレない。 マスターでのみトリガーが解釈され、トリガー元テーブルと トリガー先テーブルの両⽅のイベントがbinlogに記録され る。 マスターとスレーブでトリガーが違うと地獄が⾒える。- バイナリーパックで型が決まっているため、マスターとスレ ーブでデータ型が違うと死ぬ。 ⽂字コードが違ってもバイト数が異なって死ぬ。- 59/133
  61. 61. MBR 基本はSBR、非決定性ステートメントだけRBRで使い分け る。MBRと呼ぶのは稀。 いいとこ尽くしに聞こえなくもないけど、実際は思わぬとこ ろでRBRにフォールバックして割とカジュアルに死ぬ。 マスタースレーブでトリガーをズラして調整している時 にRBRに落ちて泣いたり。 - 何故かWHERE pkey = ?なクエリーにLIMIT 1とか付けられ てRBRに落ちて Bug#74118 の洗礼を受けたり。 - MySQL 5.1の⼀部のリビジョンだけこれがデフォルト。 弊社はこれです。。 60/133
  62. 62. 初⼼者は黙ってRBR(5.7ʼs default) 初⼼者は黙ってRBR サイレントにデータがズレるよりはエラって⽌まった⽅がマ シ データのズレを検出&リカバリーするにはpt-table- checksumとpt-table-syncが有効 pt-slave-restartは使えるけどオススメしない 61/133
  63. 63. pt-table-checksum SBRとRBRでそれぞれチェックサムを計算してテーブルに突 っ込むクエリーを発⾏ マスター上では当然SBRでもRBRでも同じチェックサム になる - スレーブではSBRで来たイベントは スレーブでチェックサ ムを計算 、RBRで来たイベントは マスターで計算されたチ ェックサムがそのままカラムに⼊る これを⽐較することができる 62/133
  64. 64. pt-online-schema-change 変更元テーブルをコピーして先にALTER TABLEを適⽤する 変更元テーブルにトリガーを仕掛けて、変更元テーブルに対 する更新がコピーしたテーブルにも反映されるようにする READ-COMMITTEDでゆっくり変更元テーブルからコピー したテーブルに⾏をコピーする コピーが終わったらロックを取ってRENAME TABLE 63/133
  65. 65. pt-online-schema-change InnoDBオンラインDDLが導⼊された5.6以降でも有効 何故なら、SQLスレッドは相変わらず1本(あるいは、同じ テーブルだとMTS使ってても追い越せない)ので、ALTER TABLEに時間がかかるとその分レプリケーションが遅れる pt-oscは細切れに⾏をコピーして、スレーブの遅れ具合をチ ェックしながらスリープを⼊れるので、レプリケーション遅 延に優しい 64/133
  66. 66. バイナリーログの⼀⽣ マスター上でコミットされた順にbinlogにエンコード binlogからrelaylogにシングルスレッドで転送(順序は保証 される) relaylogはシングルスレッドまたはマルチスレッドで適⽤ MySQL 5.5とそれ以前はシングルスレッド固定- MySQL 5.6とそれ以降はslave_parallel_workers > 1で MTS(Multi Threaded Slave) - 65/133
  67. 67. MTSのアーキテクチャー clientA connection executor storage_engine binlog binlog_dump io_thread relaylog slave_executor1 slave_executor2 slave_executor3 coordinator slave_worker1 slave_worker2 slave_worker3 storage_engine binlog slave_connection clientB master slave 66/133
  68. 68. MTSのアーキテクチャー マスターのバイナリーログがリレーログに記録されるところ までは⼀緒 1. SQL Thread(coordinator)がリレーログからイベントを取 り出す 2. coordinatorがslave̲worker̲threadにイベントを渡す3. slave̲worker̲threadはそれぞれExecutorを叩いてストレ ージとバイナリーログを更新する 4. 67/133
  69. 69. MTSのアーキテクチャー マスターのバイナリーログがリレーログに記録されるところ までは⼀緒 1. SQL Thread(coordinator)がリレーログからイベントを取 り出す 2. coordinatorがslave̲worker̲threadにイベントを渡す3. slave̲worker̲threadはそれぞれExecutorを叩いてストレ ージとバイナリーログを更新する 4. 68/133
  70. 70. MTSコーディネーター 前後のイベントが互いに⼲渉しない(順序を⼊れ替えても問 題ない)かどうかの責任を持つ ただし順序が⼊れ替わる(線形でない)ことが⼤前提の ため、シングルスレッドレプリケーションよりも結果整 合性の⾊が強い - 69/133
  71. 71. MTSコーディネーター MySQL 5.6ではスキーマが分かれていることで⼲渉しない ことを担保(5.7のslave_parallel_type= DATABASE相当) 5.7ではマスターでbinlogに記録された時の直前のコミット のタイムスタンプをベースに⼲渉しないことを担保するモー ドが登場(slave_parallel_type= LOGICAL_CLOCK) マスター上でロックが競合せずにグループコミットの中 に⼊れたってことはスレーブでも競合しないってことだ よね︖ という理屈 - 70/133
  72. 72. MTSのアーキテクチャー マスターのバイナリーログがリレーログに記録されるところ までは⼀緒 1. SQL Thread(coordinator)がリレーログからイベントを取 り出す 2. coordinatorがslave̲worker̲threadにイベントを渡す3. slave̲worker̲threadはそれぞれExecutorを叩いてスト レージとバイナリーログを更新する 4. 71/133
  73. 73. slave̲worker̲thread 独⽴して動作するため、RR(Repeatable-Read)でもマス ターと同⼀のデータベース全体のスナップショットを保証で きない 5.6ではスレーブ側のバイナリーログの中⾝は順序を保証で きない(5.7ではslave_preserve_commit_orderで LOGICAL̲CLOCKベースの順序を保証できるようになっ た) 72/133
  74. 74. イベントの識別 たとえばInnoDBログならLSN バイナリーログはファイル名とファイルの先頭からのオフセ ットバイト数 これらはマスター上でのみ⼀意に識別されるものなので カスケードすると変わる - MySQL 5.6とそれ以降のGTIDもこれらをマッピングする だけで、本質的には相変わらずこれで⾒ている - 73/133
  75. 75. CHANGE MASTER TO mysql> CHANGE MASTER TO master_log_file= '..', master_log_pos = ..; このバイナリーログのこのポジションから先を寄越せ、とい うクライアントからのリクエスト。 ポジションの指定はイベントの先頭でないといけない(イベ ントの先頭でないポジションを指定するとSTART SLAVEでI/O スレッドがエラる) バイナリーログの固定ヘッダ⻑はバージョンによって違 うけど、どうせ読み⾶ばされるので「先頭から読ませた い」時はmaster_log_pos= 1でどのバージョンでもイケ る。 - 74/133
  76. 76. master.info マスターの情報を保持するための構造。コード追う時は mi。 CHANGE MASTER TOで与えられた情報 + αが⼊ってる。 relay_log_recovery != 1の時はここからファイルとポジシ ョンの情報を復元してレプリケーションを再開する 5.6とそれ以降ではInnoDBなテーブルに記録することが可 能(master_info_repository= {TABLE|FILE} 75/133
  77. 77. master.info slave1 [localhost] {msandbox} ((none)) > SELECT * FROM mysql.slave_master_infoG *************************** 1. row *************************** Number_of_lines: 23 Master_log_name: mysql-bin.000001 Master_log_pos: 3089 Host: 127.0.0.1 User_name: rsandbox User_password: rsandbox Port: 22494 Connect_retry: 60 Enabled_ssl: 0 Ssl_ca: Ssl_capath: Ssl_cert: Ssl_cipher: Ssl_key: Ssl_verify_server_cert: 0 Heartbeat: 1800 Bind: Ignored_server_ids: 0 Uuid: 00022494-1111-1111-1111-111111111111 Retry_count: 86400 Ssl_crl: Ssl_crlpath: Enabled_auto_position: 0 1 row in set (0.00 sec) 76/133
  78. 78. relay̲log.info リレーログ(SQLスレッド, slave̲worker̲thread)の情報 を保持するための構造。コード追う時はrli。 Relay̲log̲fileとかRelay̲log̲posとか Relay̲Master̲Log̲FileとかExec̲master̲log̲posとか⼊ ってる(SQLスレッド側の使う情報) 5.6とそれ以降ではInnoDBなテーブルに記録することが可 能(relay_log_info_repository= {TABLE|FILE}) 77/133
  79. 79. relay̲log.info slave1 [localhost] {msandbox} ((none)) > SELECT * FROM mysql.slav e_relay_log_infoG *************************** 1. row *************************** Number_of_lines: 7 Relay_log_name: ./mysql-relay.000002 Relay_log_pos: 3061 Master_log_name: mysql-bin.000001 Master_log_pos: 2898 Sql_delay: 0 Number_of_workers: 0 Id: 1 1 row in set (0.00 sec) 78/133
  80. 80. レプリケーションとマスタークラッシュ バイナリーログ マスターストレージ リレーログ 影響 残ってない 未更新 受信してない なし(︖) 残ってない 未更新 受信した データ不整合(スレーブに あってマスターにない) しかもエラー (ER̲MASTER̲FATAL̲ERROR̲REA DING̲BINLOG) 残ってない 更新済み 受信してない データ不整合(マスターに あってスレーブにない) 残ってない 更新済み 受信した なしだがエラー (ER̲MASTER̲FATAL̲ERROR̲REA DING̲BINLOG) 残ってる 未更新 受信してない トランザクションロ スト 残ってる 未更新 受信した データ不整合(スレーブに あってマスターにない) 残ってる 更新済み 受信してない なし(リトライで救われる) 残ってる 更新済み 受信した なし バイナリーログが残っていない場合、その期間のPITR不可 79/133
  81. 81. レプリケーションとマスタークラッシュ sync_binlog= 1だと起こり得る範囲がぐっと狭く バイナリーログ マスターストレージ リレーログ 影響 残ってる 未更新 受信してない トランザクションロ スト 残ってる 未更新 受信した データ不整合(スレーブに あってマスターにない) 残ってる 更新済み 受信してない なし(リトライで救われる) 残ってる 更新済み 受信した なし 80/133
  82. 82. レプリケーションとマスタークラッシュ またはsemisync + log_slave_updatesでマスター切り替え バイナリーログ マスターストレージ リレーログ 影響 残ってない 未更新 受信した データ不整合(スレーブに あってマスターにない) しかもエラー (ER̲MASTER̲FATAL̲ERROR̲REA DING̲BINLOG) 残ってない 更新済み 受信した なしだがエラー (ER̲MASTER̲FATAL̲ERROR̲REA DING̲BINLOG) 残ってる 未更新 受信した データ不整合(スレーブに あってマスターにない) 残ってる 更新済み 受信した なし 81/133
  83. 83. レプリケーションとスレーブクラッシュ リレーログ master.info SQLスレッド relay̲log.info 影響 受け取ってない 記録してない 適⽤してない 記録してない なし 受け取ってる 記録してない 適⽤してない 記録してない リレーログ⼆重 受信 受け取ってる 記録してない 適⽤した 記録してない リレーログ⼆重 受信 + ⼆重適 ⽤ = 三重コミ ット 受け取ってる 記録してない 適⽤した 記録した リレーログ⼆重 受信 受け取ってる 記録した 適⽤してない 記録してない なし 受け取ってる 記録した 適⽤した 記録してない リレーログ⼆重 適⽤ 受け取ってる 記録した 適⽤した 記録した なし 82/133
  84. 84. レプリケーションとスレーブクラッシュ relay_log_info_repository= TABLE ただしInnoDB前提(innodb_flush_log_at_trx_commit = 1で次の表) - SQLスレッドのイベント適⽤と mysql.slave̲relay̲log̲infoへのUPDATEを1つのコミ ットにまとめる - 83/133
  85. 85. relay_log_info_repository= TABLE && innodb_flush_log_at_trx_commit = 1 リレーログ master.info SQLスレッド relay̲log.info 影響 受け取ってない 記録してない 適⽤してない 記録してない なし 受け取ってる 記録してない 適⽤してない 記録してない リレーログ⼆重 受信 受け取ってる 記録してない 適⽤した 記録した リレーログ⼆重 受信 受け取ってる 記録した 適⽤してない 記録してない なし 受け取ってる 記録した 適⽤した 記録した なし 84/133
  86. 86. レプリケーションとスレーブクラッシュ relay_log_recovery レプリケーションの再開時にmaster.infoのポジション情 報をアテにせず、relaylog.infoの情報を元にレプリケー ションを復元する - 受信済みだけど未適⽤の(relaylog.infoに適⽤済みと記 録されてない)リレーログは捨てる - 85/133
  87. 87. relay_log_recovery リレーログ master.info SQLスレッド relay̲log.info 影響 受け取ってない 記録してない 適⽤してない 記録してない なし 受け取ってる 記録してない 適⽤した 記録してない リレーログ⼆重 受信 + リレー ログ⼆重適⽤ = 三重コミッ ト 受け取ってる 記録した 適⽤してない 記録してない なし 受け取ってる 記録した 適⽤した 記録した なし 86/133
  88. 88. レプリケーションとスレーブクラッシュ 男らしくバックアップからリストアする 割と真⾯目に。 毎回リストアすると割り切れば、ACIDのDは無茶な⽅向 に振れて性能が稼げるお( ^ω^) - 87/133
  89. 89. レプリケーションとスレーブクラッシュ sync̲relay̲log? syncされていようとsyncされていまいと、リレーログからレ プリケーション再開位置を特定するわけではない sync̲master̲info? relay_log_recoveryならrelay̲log.infoから再開位置を特定す るのであまり重要じゃない sync̲relay̲log̲info? relay_log_info_repository != TABLEやトランザクション非対 応テーブルの場合にのみ効いてくる。ややこしいので注意。 http://dev.mysql.com/doc/refman/5.6/ja/replication- options-slave.html#sysvar̲sync̲relay̲log̲info 88/133
  90. 90. マスター側のフィルターに関するパラメーター server_id, replicate_same_server_id フィルター関連っぽくないけど。- ⾃分と同じサーバーIDのイベントは読み⾶ばす カスケードすると同じサーバーIDのmysqldがいても⼀ ⾒問題なさげに⾒えてしまう - binlog_do_db, binlog_ignore_db そもそもバイナリーログに記録されなくなる。- カレントデータベース基準。- 個⼈的に推奨しない。- 89/133
  91. 91. スレーブ側のフィルターに関するパラメーター SQLスレッドでフィルター なので、I/Oスレッドはフツーに受信してリレーログまで 吐く - replicate_do_db, replicate_ignore_db- replicate_do_table, replicate_ignore_table- replicate_wild_do_table, replicate_wild_ignore_table- replicate_rewrite_db 90/133
  92. 92. レプリケーションフィルターの評価順 フローチャートになってるので⾒やすい MySQL :: MySQL 5.6 リファレンスマニュアル :: 17.2.3 サーバーがレプリケーションフィルタリングルールをどのよ うに評価するか マスターとスレーブで意図的に不整合を起こさせよう って いうんだから業が深い 91/133
  93. 93. レプリケーションで垂直シャード table1 table2 table3 binlog replicate_do_table= t able1 table1 replicate_do_table= t able2, table3 table2 table3 master slave slave 92/133
  94. 94. マスターとスレーブで バージョンが違ってもいい(レプリケーションがサポートさ れるのは原則リリース系列1世代) スレーブを先にバージョンアップするパターンのみ 全部のスレーブを先にバージョンアップしてマスター切り替 えして、旧マスターをバージョンアップして新マスターにぶ ら下げるとローリングアップグレードとか 93/133
  95. 95. マスターとスレーブで ストレージエンジンが違ってもいい(だがマスターを BLACKHOLEはやめておけ) マスターはInnoDBでトランザクション保護、集計⽤スレー ブはMyISAMでスキャンしまくる遊び(あるいは、MyISAM は容量効率がいいし) マスターはInnoDBで保護、参照⽤スレーブにMroonga(参 照ロックフリー、全⽂検索、カラムナー) ローリングアップグレードと同じ要領で、MyISAMから InnoDBに変更したり 94/133
  96. 96. マスターとスレーブで インデックスがあったりなかったりしていい(カラムはやめ ておいた⽅が無難) RSU(Rolling Schema Update)って呼ぶこともある。 呼ばないこともある。 - 5.6のInnoDBオンラインDDLでRSUがかなりやりやすく- ただしあんまり差があると管理が⾯倒 95/133
  97. 97. これまでのレプリケーションの制約 I/Oスレッド - リレーログ - SQLスレッド で1組 5.6からSQLスレッドは並列化可能に- I/Oスレッドが1本しかないということは、「スレーブか ら⾒たマスターは1つしか存在できない」 マスターから⾒たスレーブはいくつあってもいい(た だのクライアントなので、(性能を考えなければ) max_connections未満ならいくらでも) - 96/133
  98. 98. 複数のマスターを持ちたい理由 集計⽤スレーブ あっちのサーバーのデータとこっちのサーバーのデータ をJOINしたい - 集計⽤と割り切ればHDDのRAID5で容量を稼ぐという選 択肢もありだし - シャードの集約 複数のシャードをまとめてサーバー削減したい- 97/133
  99. 99. N対1レプリケーション 通称えぬいちレプリケーションまたはどあきレプリケー ション 「1つのマスターしか設定できないなら、定期的にマスター を切り替えればいいじゃない」 do-aki/N1Repl: master n : slave 1 replication for mysql 98/133
  100. 100. N対1レプリケーション master1 slave master2 START SLAVE Binlog Dump Applying CHANGE MASTER TO Binlog Dump Applying CHANGE MASTER TO Binlog Dump 99/133
  101. 101. N対1レプリケーション 実はMySQL Utilitiesにもmysqlrplmsというどあきレプリケ ーションスクリプトがある ただしこちらはGTID必須 mysqlrplms ̶ Set Up and Start Replication Among a Slave and Multiple Masters 100/133
  102. 102. (Native) Multi Source Replication MySQLでは5.7、MariaDBでは10.0から 「1つのI/Oスレッドが1つのマスターしか設定できないな ら、I/Oスレッドごと横に増やせばいいじゃない」 I/Oスレッド, リレーログ, SQLスレッド(MTS可)を「チャン ネル」(MariaDBは「コネクション」)という単位で複数起 動する もちろんチャンネル間のデータ競合や順序の保証はユー ザーがしなければいけない - 101/133
  103. 103. (Native) Multi Source Replication master1 slave_channel_1 slave_channel_2 master2 START SLAVE FOR CHANNE L 1 Binlog Dump Applying START SLAVE FOR CHANNE L 2 Binlog Dump Applying 102/133
  104. 104. お⼿軽シャード集約 スキーマが分かれている場合 インポートだけ間違えなければ⼤丈夫 スキーマは同じだけどテーブルが分かれている場合 インポートだけ間違えなければ⼀応⼤丈夫 同じ名前空間のテーブルがある ユニークキーは本当にユニーク︖ サロゲートキーは︖ MySQLやSSDとかの話 前編 103/133
  105. 105. GTID Global Transaction IDentifier サーバー識別⼦(マスターの@@server_uuid)、ソースを 追っかけるならSIDNO(Source ID NO) datadir/auto.cnfに保管されるので、リストア時に注 意 - トランザクション識別⼦(マスター上でトランザクショ ンがコミットされた連番)、ソースを追っかけるなら GNO(Group NO) - トランザクションを⼀意に識別するだけで、バイナリーログ のイベントを⼀意に識別するわけではない これ意外と⾒落としがち- 104/133
  106. 106. GTIDとマスター バイナリーログにGTIDを埋め込むようになる…くらいしか 違いはない とはいえgtid_mode= ONにはenforce_gtid_consistency= ON が必要なので、マスターの振る舞いとしては違いは少なくと もサーバーとしての振る舞いはちょっと違う 明らかにトランザクションアンセーフなステートメント の実⾏を拒否するようになる - 105/133
  107. 107. GTIDとI/Oスレッド master_auto_position= 1の場合、「このファイルのこのポ ジションから寄越せ︕」の代わりに、「この(=スレーブが 既に適⽤済みの)GTID 以外 のバイナリーログを頼む」に なる サーバー側が動的にファイル名とポジションに変換して 送信してくれる。 - Commandが”Binlog Dump”から”Binlog Dump GTID”になる。⾖。 - マスターに伝える「適⽤済みのGTID」はgtid_executed変数 に⼊っている。 106/133
  108. 108. gtid̲executedの保管 バージョン log̲bin 保存先 再起動時の gtid̲executedの復元 5.6 OFF N/A N/A(GTIDが有効化 できない) 5.6 ON バイナリーログ 最新のバイナリーロ グの Previous̲gtids̲lo g̲eventと最新のバ イナリーログの Gtid̲log̲eventを 全部⾜したもの 107/133
  109. 109. gtid̲executedの保管 バージョン log̲bin 保存先 再起動時の gtid̲executedの復元 5.7 OFF mysql.gtid̲excute d テーブルから (COMMITのたびに mysql.gtid̲execut edに保存) 5.7 ON バイナリーログ&テ ーブル バイナリーログか ら。テーブルへの記 録はバイナリーログ のフラッシュの時だ け 108/133
  110. 110. GTIDとSQLスレッド GTIDの連番部分(GNO)は気にしない これから実⾏するトランザクションのGTID(gtid_next)が 実⾏済み(gtid_executedに含まれる)の場合、実⾏しない (スキップする) これによってスレーブクラッシュ時の「リレーログの⼆ 重適⽤」が完全に回避できる - sql/sql̲parse.cc:mysql̲execute̲commandの中で分 岐するので、エグゼキューターがそもそも(ほぼ)動か ない。 - エグゼキューターなので、SQLスレッドに限らずフツー のスレッドでも同じ動作。 - 109/133
  111. 111. GTIDの有効化 masterslave OFF OFF̲PERMISSIVE ON̲PERMISSIVE ON OFF ○ ○ ○ × OFF̲PERMIS SIVE ○ ○ ○ × ON̲PERMISS IVE × ○ ○ ○ ON × ○ ○ ○ 110/133
  112. 112. GTIDの有効化 OFF GTIDを振らない。GTIDの振られたイベントが来るとエラる OFF̲PERMISSIVE (5.7から) GTIDを振らないけど、GTIDの振られたイベントが来ても⽂句 を⾔わない ON̲PERMISSIVE (5.7から) GTIDを振るけど、GTIDの振られてないイベントが来ても⽂句 を⾔わない ON GTIDを振るし、GTIDの振られてないイベントが来るとエラる 111/133
  113. 113. 準同期レプリケーション 通称semisync ここを同期にする Executorがストレージエンジンに書くa. Executorがバイナリーログに書くb. Binlog Dump Threadがバイナリーログを読むc. I/O ThreadがBinlog Dumpからイベントを受け取っ てリレーログに書く d. I/O ThreadからBinlog DumpにACKを返すe. SQL Threadがリレーログからイベントを読み取って⾃ ⾝のExecutorを叩く f. 112/133
  114. 114. 準同期レプリケーションのパラメーター rpl_semi_sync_master_timeout デフォルトが10000(ミリ秒、つまり10秒)と⼤きい- rpl_semi_sync_master_wait_no_slave OFFにすると、スレーブが全滅すると⾃動でAsyncレプリ ケーションにフォールバックする - 113/133
  115. 115. 準同期レプリケーションの拡張 at 5.7 rpl_semi_sync_master_wait_for_slave_count いくつのI/O ThreadがACKを返したらマスター上でOKと されるかを指定可能に - rpl_semi_sync_master_wait_point= {AFTER_SYNC| AFTER_COMMIT} マスター上で、ACKを待ってからストレージエンジンに 書き込むか、ストレージエンジンに書き込んでからACK を待つか - 「ロスレス準同期」と⾔ってるやつ- 114/133
  116. 116. その他のレプ リケーショ ン︖ 115/133
  117. 117. 仮想完全同期レプリケーション 通称Galera Cluster 本家codershipのGalera Cluster for MySQL, Percona実 装のPercona XtraDB Cluster, MariaDB実装のMariaDB Galera Clusterがある - バイナリーログモジュールを使ってるけどバイナリーログと は別のファイルを吐き出す InnoDBストレージエンジンのみサポート binlog̲format= ROW固定 Deadlock detectionじゃなくてLocal certification failureな んだっ⼿⽻先 116/133
  118. 118. Galera Cluster ローカルノードにトランザクションを展開1. COMMIT前にGalera Cacheに書き込み2. Galera Cacheのプロパゲート3. 他ノードからACK4. ローカルノードでCOMMIT完了5. 他ノードでCOMMIT6. 117/133
  119. 119. Percona XtraBackup レプリケーション︖ グローバルロックをかけてLSNを取り出すa. テーブルスペースファイルのコピーb. コピー中、InnoDBログをスキャンして、開始時以降の LSNのログを全て記録する c. コピーしたテーブルスペースにコピーしたログファイル を適⽤する(クラッシュリカバリー相当) d. これができるってことは頑張ればInnoDBログのストリーム によるレプリケーションもできるんじゃ…︖ 俺はがんばらない- 118/133
  120. 120. mysqlbinlog -R –stop-never –raw マスターから⾒るとI/Oスレッドに⾒えるmysqlbinlog -Rに バイナリーログの末尾まで⾏っても終了しない--stop-never オプションを付け binlogデコードをかけずにそのままファイルに落とす--raw オプションを付けると バイナリーログのストリームバックアップができます 119/133
  121. 121. Facebook MySQLのmysqlbinlog semisyncスレーブになれるようなオプションが拡張されて る マスターとスレーブは複数の違うDCに配置されてるらしく て マスターと同じDCにバイナリーログ保管⽤のmysqlbinlog さんがいる DC間はAsync, DC内(mysqlbinlog)はSemisyncにすること で、レイテンシーとバイナリーログの保全を両⽅担保 Yoshinori Matsunobuʼs blog: Semi-Synchronous Replication at Facebook 120/133
  122. 122. Binlog Events I/Oスレッド相当の実装とbinlogデコーダーの実装ライブラ リー 地雷が埋まってるらしい。- MySQL Binlog Events でストリーム処理してみた #MySQLUC15 - Labs にある”Hadoop Applier”はこれを使った実装に書き換 えるとか書き換えないとか 121/133
  123. 123. InnoDB Memcached Plugin 122/133
  124. 124. InnoDB Memcached Plugin innodb_api_enable_binlogを有効にするとbinlog吐ける イベントは全てRBR がんばれば「トランザクション対応永続化分散 memcached」が出来るかも知れない innodb_api_trx_levelのデフォルトはREAD- UNCOMMITTEDなので要変更 - innodb_api_bk_commit_intervalのデフォルト5秒も変え た⽅が良さそう - 123/133
  125. 125. さあみなさん お待ちかね 124/133
  126. 126. 「NOW関数は現 在時刻を返さな い」の謎に迫る 125/133
  127. 127. NOW関数 NOW() は、ステートメントが実⾏を開始する時刻を⽰ す定数時間を返します。 さらに、SET TIMESTAMP ステートメントによっ て、 ..snip.. タイムスタンプをゼロ以外の値に設定する と、後続の NOW() が起動されるたびに、その値が返さ れます。 http://dev.mysql.com/doc/refman/5.6/ja/date-and-time- functions.html#function̲now 126/133
  128. 128. NOW関数 mysql56> SELECT NOW(); 2016-02-18 19:37:18 mysql56> SELECT NOW(); 2016-02-18 19:37:19 mysql56> SET timestamp= 1455791802.172832; mysql56> SELECT NOW(); 2016-02-18 19:36:42 mysql56> SELECT NOW(); 2016-02-18 19:36:42 127/133
  129. 129. NOW関数とバイナリーログ 安全でないと⾒なされない非決定的関数。 これらの関 数は決定的ではありませんが、ロギングおよびレプリケ ー シ ョ ン目 的の場 合は安 全と し て処 理さ れ ま す: CONNECTION̲ID()、CURDATE()、CURRENT̲DATE ()、CURRENT̲TIME()、CURRENT̲TIMESTAMP()、 CURTIME()、LAST̲INSERT̲ID()、LOCALTIME()、 LOCALTIMESTAMP()、NOW()、UNIX̲TIMESTAMP ( )、U T C ̲ D A T E ( )、U T C ̲ T I M E ( )、お よ び UTC̲TIMESTAMP()。 http://dev.mysql.com/doc/refman/5.6/ja/replication-rbr- safe-unsafe.html 128/133
  130. 130. NOW関数とバイナリーログ # at 4381 #160212 17:23:20 server id 1056 end_log_pos 4466 Query thread_i d=43 exec_time=0 error_code=0 SET TIMESTAMP=1455265400/*!*/; BEGIN /*!*/; # at 4466 #160212 17:23:20 server id 1056 end_log_pos 4710 Query thread_i d=43 exec_time=0 error_code=0 SET TIMESTAMP=1455265400/*!*/; INSERT INTO t1 VALUES (1691643253,'JBbKOfG7O3qp66Aa5yY8QelD4WL77eKIpneDJ nCbq2Oo0QM6Pm6jOrxLDASCpgXWS1cnooMXjeJj5ahMCnxTXuqkxIxmyK8QLk52PJZ8ykjvA P9N46sbtiKq09SqTc') /*!*/; # at 4710 #160212 17:23:20 server id 1056 end_log_pos 4737 Xid = 943518 COMMIT/*!*/; 129/133
  131. 131. レプリケーション でしこたま痛い目 を⾒た の先⼈ イル カ㌠から 130/133
  132. 132. これからレプリケー ション で痛い目を⾒ る でできることが増 えていくゾウ㌠へ 131/133
  133. 133. 楽しい よ︕︕1 132/133
  134. 134. Questions and/or Suggestions? 133/133

×