Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
さいきんの InnoDB Adaptive Flushing (仮)
Search
Takanori Sejima
September 07, 2017
Technology
24
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB のお話です。
Takanori Sejima
September 07, 2017
More Decks by Takanori Sejima
See All by Takanori Sejima
(きっとたぶん)人材育成や教育のような何かの話
sejima
0
870
互換性のある(らしい)DBへの移行など考えるにあたってたいへんざっくり
sejima
1
3.7k
NAND Flash から InnoDB にかけての話(仮)
sejima
0
25
InnoDBのすゝめ(仮)
sejima
0
27
さいきんのMySQLに関する取り組み(仮)
sejima
0
21
sysloadや監視などの話(仮)
sejima
0
22
TIME_WAITに関する話
sejima
0
34
MySQLやSSDとかの話 その後
sejima
0
22
binary log と 2PC と Group Commit
sejima
0
17
Other Decks in Technology
See All in Technology
なぜ Platform Engineering の土台に Kubernetes を選ぶのか
r4ynode
2
590
ACE-Step-1.5で見る 音楽生成AIのしくみと“破綻だけ直す”Retake機能の開発【zennfes spring 2026 登壇資料】
personabb
1
130
チームで進めるAI駆動アジャイル×ウォーターフォール
kumaiu
0
150
Oracle AI Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
4
2.9k
RSA暗号を手計算したくなること、ありますよね?? (20260615_orestudy6_rsa)
thousanda
0
240
失敗を経て、Harness Engineering で 大切にしたいことを考える / Learning from Failure: What Matters in Harness Engineering
bitkey
PRO
1
310
Socrates × Looker 〜セマンティックレイヤーで進化するデータ分析エージェント〜
hanon52_
3
2.1k
2026TECHFRESH畢業分享會 - 原生還是跨平台? App 開發踩坑實錄
line_developers_tw
PRO
0
820
2026TECHFRESH畢業分享會 - 葬送的通靈師:化系統與用戶雜訊成行動訊號
line_developers_tw
PRO
0
810
連合学習と機密コンピューティング
lycorptech_jp
PRO
0
100
Dario Amodi『Policy on the AI Exponential』を理解する
nagatsu
0
220
失敗を資産に変えるClaude Code
shinyasaita
0
470
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Darren the Foodie - Storyboard
khoart
PRO
3
3.4k
Bash Introduction
62gerente
615
220k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
940
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Accessibility Awareness
sabderemane
1
140
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
240
A Soul's Torment
seathinner
6
2.9k
Prompt Engineering for Job Search
mfonobong
0
340
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
140
Transcript
さいきんの InnoDB Adaptive Flushing (仮) 瀬島 貴則
免責事項 - 本資料は個人の見解であり、私が所属する組 織の見解とは必ずしも一致しません。 - 内容の一部に偏ったものがあるかもしれません が、各自オトナの判断でよろしくお願いします。 2
自己紹介 - わりとMySQLでごはんたべてます - 3.23.58 あたりから使ってます - 一時期は Resource Monitoring
もよくやってま した - さいきんはハードウェアの評価したり、 Linux の TCPプロトコルスタックまわり調べたりもして ました - Twitter: @ts4th 3
今日のお題 - MySQL 5.7 に至るまでの InnoDB Adaptive Flushing を振り返りつつ -
InnoDB Adaptive Flushing によって発生する 書き込み処理について整理して - うまいこと書き込み処理を最適化できないか考 えます 4
5.7はかなり高度に進化しています - 昔と比べてかなり進化しているので、いきなり 5.7のソースコードを読んだり、5.7の改善点を理 解しようとしても、とっつきにくいかもしれませ ん。 - 5.5や5.6から見ていった方がわかりやすいと思 うので、今回は5.5や5.6なども踏まえてお話しま す
5
では はじめます 6
InnoDB Adaptive Flushing とは - MySQL5.1の時代に、InnoDB Plugin 1.0.4 で 追加されました。
- 5.5 でInnoDB本体に組み込まれ、5.6 、5.7でさ らに良くなりました。 - ただ、公式ドキュメントで解説しきれてない部分 もあると思うので、そのあたりを振り返ってみま す 7
基本的なところから 振り返って いきましょう 8
InnoDBの基本的なファイル群 - ibdata1 - internal data dictionary, undo log, change
buffer, double write buffer などが含まれます(今回は紙幅の都 合でそのあたり割愛します) - ib_log_file* - transaction log・・・REDO Logs(Write Ahead Log) - *.ibd - table space・・・table の data や index 9
ざっくりいうと、 InnoDB は - Transaction で発生したデータの更新は ib_log_file* に溜め込んで - 裏でチマチマ
*.ibd に flush - ib_log_file* は固定長の(InnoDB起動時にサイ ズが決まる)ログなので、使い切ると、 Transaction の更新内容をログに書けなくなり ます。そうならないよう、裏で *.ibd に反映してい るわけです 10
REDO Logs(Write Ahead Log) - 更新内容は先ず log に書いて、 table space
に は裏でゆっくり反映 - WALはMySQL以外のRDBMS でも用いられる手法 - log への書き込みは sequential write になるの で、HDDみたいな random I/O 遅い block device でもそれなりに速い - table space に反映するとき、更新処理をまとめ ることもできる。 (write combining) 11
Log Sequence Number(LSN) - transaction log(ib_log_file*) のサイズは InnoDB の起動時に innodb_log_file_size
で 指定して決める(固定長) - transaction log は ring buffer というか cyclic というか circular fashion - InnoDB が transaction log を初期化して以降、 log の buffer に書いてきたバイト数が Log Sequence Number。 12
Last checkpoint at - buffer pool 上にある更新内容を、LSN 的に *.ibd にどこまで反映したか示すものが
Last checkpoint at。 - SHOW ENGINE INNODB STATUS で見える やつ - 可能であれば、 (LSN - Last checkpoint at) は監視項 目に加えておくのがオススメ - 実はかなり重要な情報です 13
oldest_modification - ibdata1 や *.ibd は、page (default 16KB)という単位で管 理されており -
page の構造体には、 oldest_modification というメンバ変 数がある - その page が dirty になった最初のイベントが書かれている log の position(LSN) 、それが oldest_modification - dirty page をflushしてdiskに同期させると、その page の oldest_modification は 0 でリセット 14
write combining - I/O が page 単位なので、同一の page への更 新は、まとめて
disk に flush できる。 - 同一の page に格納されている複数の row への更新を、一回で disk に書けることも - log に溜めこみ、まとめて flush できるとお得 - Last checkpoint at の進み方と disk I/O は、必 ずしも比例しない。 15
図に描くとこう 16
InnoDB Adaptive Flushing の必要性 - log は有限なので使いきってはいけない - 具体的に言うと、(LSN -
Last checkpoint at) が 75%くらいになると、強制的に dirty page の flush 走る。そうなると刺さりがち。 - 75%というのは定数ではなく、 log/log0log.cc の log_calc_max_ages() で計算してる - なるべく強制 flush 走らないよう、 adaptive に flushing する機能が必要だったのです 17
InnoDB Adaptive Flushing ない時代 - InnoDB Adaptive Flushing がない時代、(具体 的には
InnoDB Plugin 1.0.4 より前の時代)い ずれかの状況にならないと flush されにくかった - buffer pool 上で dirty page の比率が innodb_max_dirty_pages_pct(昔はdefault90、いまは default 75)を超える - REDO Logs の使用率が約75%超える 18
原初の InnoDB Adaptive Flushing - 5.1や5.5 の InnoDB Adaptive flushing
は、 master_thread という background で動いてる thread が、 innodb_io_capacity に応じて 他の タスクの合間に flush してた - むかしの master_thread は、単一の thread で複数の background task を goto でこなしていた。 - InnoDB がどういう task を background でやってるかわ かりやすいので、一度、 5.5 の master_thread 読んで みるのオススメです。 19
5.5以前の innodb_io_capacity - io_capacity は正確にいうと iops ではない - master thread
が一秒間にどれくらい page の I/O してもいいか、という値 - (SELECT が多いなどで) disk read が多いと きは、 dirty page の flush を加減してた - 例えば、ピークタイムに dirty page をあまり flush しない ことがあったとしたら、それは read が多いことが原因 だったりした 20
- 5.5 以前の InnoDB Adaptive Flushing は、 innodb_io_capacity の範囲内で flush
してた ので - 高速な block device だからといって innodb_io_capacity 上げすぎると、 write combining が効かない - REDO Logs を溜めずにつどつどflushしてしまう 21
もったいない 22
5.6以降の InnoDB Adaptive Flushing - で、5.6 や5.7でかなり良くなったんですが - MySQL Performance
Architect のDimitriK の 資料 から図を拝借すると、現状こうです 23
24
まずは5.6ベースで 一つ一つ 見て行きましょう 25
5.6 以降で何が変わったのか・その一 - 公式ドキュメントとソースコードの乖離が激しく なった - ただ、先日久々に https://dev.mysql.com/ みたら、だい ぶ充実してきているように見えました
- 最近は https://github.com/mysql/mysql-server でも change log が読めるし、change log から対応する WorkLog を辿りやすくなった - WorkLog にコードの修正方針などがまとめられている ので、とても調査しやすい OSS ですね 26
5.6 以降で何が変わったのか・その二 - back ground thread の種類が劇的に増えた - 5.5以前だと master_thread
でこなしていたタスクが複 数の thread で分散 - 特定のタスク(purge や dirty page の flush など)が重 い場合、他のタスクがそれに引っ張られてしまう場合が あったが、それが軽減された 27
5.6 以降で何が変わったのか・その三 - 関連する parameter 増えた&意味変わった - 重要なのはこのあたり - innodb_adaptive_flushing_lwm(lwmは
low water mark の略) - innodb_io_capacity - innodb_io_capacity_max - innodb_max_dirty_pages_pct_lwm - innodb_lru_scan_depth 28
page cleaner thread - MySQL5.5までは、 InnoDB で master thread と呼ばれる
thread が色々やってた - dirty page の flush - change buffering - purge - 5.6 でこれらの機能が複数の thread に分割 - 5.6 で追加された thread の一つが page cleaner thread 29
flush list と LRU list - buffer pool 上の page
は、昔から二種類の list で管理されている - flush list は更新された順(oldest_modification 順)に dirty page を管理 - LRU list は、すべての page を対象に、参照さ れた順に管理 - 5.6 以降では page cleaner thread がこれらに 対して back ground でタスクをこなす 30
5.5以前の LRU list - 5.5 以前で LRU list が参照されるケースの一 つは、
buffer pool の page があふれたとき - disk 上のデータを読み込むとき、空き page なかった ら、最も参照されていない page を破棄する。 - もし、その page が dirty だったら、 disk に flush してか ら破棄 - foreground の thread は flush 終わるまで待たされる - flush 終わって page を破棄するまで、 disk から データが読めない 31
page cleaner thread のタスク・その一 - 5.5以前は buffer pool をぜんぶ使い切る仕様 だったが、
5.6 からは innodb_lru_scan_depth で指定されただけ、 予め buffer pool の free page を確保しておくようになった - 関数的には - MySQL5.6 では buf_flush_LRU_tail() 32
buf_flush_LRU_tail() - page cleaner thread は一定間隔でLRU listを 参照し、 innodb_lru_scan_depth で指定され
ただけ free page を確保しようとする。その際、 参照されてない page から破棄する。 - page を破棄する際、 その page が dirty であ れば disk に flush する。複数あればまとめて flush する 33
- 常時 free page 確保してあるので、他の thread は free page 確保するために
dirty page の flush を待たなくて良くなった - innodb_lru_scan_depth は、 free page 枯渇し ないなら、そんなに上げなくてもよいのでは? - buffer pool の miss hit が多くて free page 減りがちな ら、増やすことを検討してもよいかも 34
ここが LRU List を見てると 35
page cleaner thread のタスク・その二 - flush list を見て dirty page
を flush する - 5.6でここのアルゴリズムが賢くなった - 関数的には - MySQL5.6 だと page_cleaner_flush_pages_if_needed() 36
page_cleaner_flush_pages_if_needed() - MySQL 5.6から、 一秒間に flush する page の数を REDO
Logs の使用率に合わせてコント ロールするようになった - REDO Logs の使用率が innodb_adaptive_flushing_lwm を超えない限りは積極 的に flush しない - innodb_io_capacity_max 重要 - REDO Logs の使用率が(とてもざっくり) 60% くらいに なると io_capacity_max で指定しただけ flush 37
- REDO Logs の使用率に比例して flush が激し くなる == innodb_io_capacity_max に近づくの
で、書き込みの多いサーバに高性能な block device を割り当てると、 default の設定でもそこ そこ flush するようになった - 逆に、書き込みの少ないDBだと、 REDO Logs の使用 率低いので、 dirty page はちょっとずつしか flush され ない。安価なハードウェアでもそこそこ動く 38
(これは私見ですが) - 設計を見る限り、 5.5 以前の InnoDB Adaptive Flushing は、 HDD
のような低速な block device をメインターゲットにしてたのでは? - 新しい高性能なハードウェアを活かすために は、新しい MySQL へ移行していくのが無難。 39
これが Flush List 見てると 40
このへんが log の 使用率に 比例してる という話 41
innodb_max_dirty_pages_pct_lwm - この parameter が default の 0 じゃないなら -
REDO Logs の使用率 と buffer pool の dirty page の比率 を比較して、flush の頻度が変わ る - transaction log より buffer pool の方がサイズ 大きいケースがほとんどだと思うので、そこまで 意識しなくてもいい気がする 42
buffer pool の dirty page の比率を 見てるのは この部分 43
しかし5.6の page cleaner は未完成 - page_cleaner: aggressive background flushing というバグレポートがあります
- idle 気味なとき、 innodb_io_capacity(maxで はない)全開まで flush してしまうケースがあり える - もしこれが困るなら、 innodb_io_capacity 下げ ても良いのではないかと 44
そして、 MySQL5.7 の InnoDB Adaptive Flushing は さらなる進化を遂げた 45
MySQL 5.7 での大きな変更点 - 5.7から、 flush する page の数を決めるとき、 REDO
logs の使用率以 外も考慮するようになった。詳しくは こちらのWorkLog に - 改善点はいくつかあるのだが、 InnoDB Adaptive Flushing 的にポイン トは二つ。 - REDO Logs の使用率だけではなく、更新頻度も考慮 - もう一つは、buffer pool instance ごとの dirty page の偏りを考慮 - 関数的には、 5.6の page_cleaner_flush_pages_if_needed() が大幅 にリファクタリングされ、5.7では page_cleaner_flush_pages_recommendation() になった 46
page_cleaner_flush_pages_recommendation() 47 - REDO Logs の使用率だけではなく、更新頻度も考慮。 - 「高頻度で REDO Logs
に書いてるんだけど、 REDO Logs の使 用率が低いので innodb_io_capacity_max で指定しただけ flush してくれない」という事態が回避できるようになる。 - REDO Logs の使用率が約75% くらいになると強制的に dirty page が flush されるので、「REDO Logs 使い切りそうなペースで 更新されてるならば、innodb_io_capacity_max で指定されてるま で flush して、 log 使い切るのを防ごう」という理由かな?
page_cleaner_flush_pages_recommendation() - buffer pool instance ごとの dirty page の偏りを考慮。 -
InnoDB の buffer pool は複数の instance に分割できるのだが、 5.7 か ら、古い dirty page の多い instance は flush を多く、少ない instance は flush を少なくするようになった。5.6以前は instance ごとに dirty page の 偏りができていた可能性があったけど、改善された。 - 5.6 は 複数の buffer pool instance があった場合、必ずしも「より古い dirty page を flush する」という挙動になるとは限らなかった。「instance ご とに dirty page を N page ずつ flush する」という挙動になっていた。5.7 から、「古い dirty page をたくさん持ってる buffer pool instance はたくさん dirty page をflushする」という挙動になったので、 write combining 的に有 利なはず。 48
さらに MySQL5.7 では - page cleaner thread が複数スレッドに対応し た。 -
buffer pool instance が複数あれば、最大で instance の数だけ page cleaner thread が並列して flush できる - innodb_page_cleaners というパラメータで、 dirty page を flush するスレッドの数をコント ロールできる。 49
とりあえず、 5.6 以降では - 5.5 以前から 5.6 に移行するだけで、 InnoDB Adaptive
Flushing が賢くなる - 5.7 ならより賢い - 高速な block device 使ってるなら、MySQLの バージョン新しくした方がよい - InnoDB Adaptive Flushing が賢くなってるので、 MySQLのバージョン新しくするだけで、 dirty page の flush 周りが改善する 50
InnoDB Adaptive Flushing の勘所 - 使い方にあわせてチューニングできるパラメー タが、たくさんあるのですが - 基本はやはり、 innodb_log_file_size
ですね。 必要なら、 innodb_log_file_size は GB単位で 指定してよいのでは。 - あとはinnodb_io_capacity_max ですかね。 51
まずは innodb_log_file_size - REDO Logs を使い切ると、強制的に dirty page が flush
されまくって重いので、ピークタイ ムに枯渇しない程度は欲しい - ただ、REDO Logs 多すぎるとクラッシュリカバ リに時間が掛かるし、ファイルシステムのキャッ シュ(Linuxだとpage cache)にメモリをたくさん 使われてしまう 52
ピークタイムの REDO Logs の使用率 - (個人的見解ですが)ピークタイムでも使用率 は、 50~60% 以下でよいのでは? -
(LSN - Last checkpoint at) が REDO Logs の総量の 75% くらいまで行くと、 Transaction がブロックされる可 能性が出てくる。(5.6以降は)使用率60% くらいになる と、 innodb_io_capacity_max まで flush するケースが ある。余裕残してもよいのでは - REDO Logs の残量を適度に残せるようチュー ニングするのがオススメ。 53
5.6 の方が 75% くらいになりやすい? - 5.6 は REDO Logs の使用率が
60% くらいに なるまで、 io_capacity_max まで flush しにく かったので、 REDO Logs の使用率が 75% く らいになりやすかったのでは? - 5.7 は更新頻度高ければ、使用率低くても innodb_io_capacity_max まで flush するの で、 REDO Logs のサイズが 5.6 より少なくて も、使用率上がりにくいのでは。 54
5.7 と innodb_io_capacity_max - 5.7 は REDO logs の使用率だけでなく、更新 頻度もみて
dirty page をいくら flush するか決 める。故に、REDO logs の使用率低くても、 innodb_io_capacity_max まで flush する可能 性がある。上げすぎない方がよい - ただ、innodb_flushing_avg_loops であるてい ど調整可能。 55
innodb_flushing_avg_loops - REDO logs の更新頻度も見て flush の頻度を 決めるのだが、(ざっくりいうと)そのサンプリン グ周期は、innodb_flushing_avg_loops で調整
可能 - innodb_flushing_avg_loops をうんと大きくすれば、一 瞬だけ更新がバーストするDBでも、 innodb_io_capacity_max まで flush しにくいはず 56
というように、 MySQL 5.7 の InnoDB Adaptive Flushing は、 様々なワークロードに合わせて チューニングできるんです
57
MySQLはハードウェアの進化に追随している - Dimitri という人は(たぶん)十数年以上にわ たって MySQL の benchmark を取り続け、新 しいハードウェアの性能を活かせるよう、ボトル
ネックを調査し続けてます - MySQLの新しいバージョンが出るたびにその 成果が反映されているので、 MySQL はハード ウェアの進化に追随し続けてる OSS と言って 良いでしょう 58
おまけ - 次期メジャーバージョンの MySQL 8.0でも、 InnoDB はいろいろ改善されるのですが - Facebook からの
feature request や、 Percona の patch が取り込まれるようです。 - 今後も引き続き InnoDB が進化していくのは、 ありがたい限りですね。 59
まとめ - 最近の InnoDB Adaptive Flushing はかなり 賢いです。オススメです。 - 最近のハードウェア使ってる人は、少なくとも5.6以降、
できれば5.7を使うのが良いでしょう。 - (LSN - Last checkpoint at) を意識しましょう - 高性能なハードウェア使ってるなら innodb_io_capacity_max 上げてもOKですが、上げす ぎないよう注意しましょう。特に 5.7 では気をつけましょ う。 60
参考 - Configuring InnoDB for MySQL 5.6: innodb_io_capacity, innodb_lru_scan_depth -
MySQL 5.6: IO-bound, update-only workloads - InnoDB adaptive flushing in MySQL 5.6: checkpoint age and io capacity - InnoDB Deep Talk #2 (仮) に引っ張りだされま した。 61
おわり 62