InnoDB の「メモリ」と「ディスク」の話

技術系ノウハウ

メモリ不足で処理が重くなるのは分かるが、具体的にどういう流れなのかよく分かってなかったので、InnoDB のメモリ、ディスク周りを整理

メモリとディスクは別物

基本的な話。

  • メモリ・・・作業中のデータを置く場所。一時的。
  • ディスク・・・データの保管場所。永続的。

InnoDBの更新処理

UPDATE や INSERT が来たとき、InnoDB はいきなりディスクに書きにいかず、更新対象のページ(16KB)をバッファプールに読み込み、まずメモリ上で書き換える。

更新されたページは「汚れたページ(Dirty Page)」という扱い。
ディスクのデータは古いまま、メモリのほうが最新の状態。SELECTはメモリのデータを返してくれるので、ユーザー体験として遅延はなし。

ディスクの整合性を保つ仕組み – Write-Ahead Logging

メモリだけ更新して電源が落ちたら、最新のデータは消えるので、Redo Logでそれを防いでいる。
更新内容をログとしてシーケンシャルに書き出し、仮にメモリが吹き飛んでも Redo Log を再生すれば復旧可能→永続性担保

Dirty Pageからディスクに書き込むタイミング

負荷の少ないタイミングでInnoDB が少しずつ書き戻す(flush)。
例)

  • Dirty Page の割合が増えてきたとき
  • Redo Log が詰まりそうなとき
  • バッファプールに空きがなく、新しいページを載せたいとき
  • バックグラウンドで余裕があるとき

「暇なときに勝手に掃除する」イメージ。
アクセスが少ない時間帯ほどディスクへの書き戻しが進むので、業務が混んでいる時間に余計な負荷が乗りにくい。

メモリ不足になると重くなる仕組み

  • Dirty Page をディスクに書き戻さないとバッファプールから追い出せない。
  • メモリが足りなくなってくると、追い出すために強制的に flush が走り始める。

これが頻繁になると、ディスク I/O はどうしても増えてしまい、結果として遅延が体感できるようになってくる。
悪化すると、OS がディスクをメモリとして使い始めてしまい、遅さが桁違いになる。(スワップ)

InnoDB の状態確認

SHOW ENGINE INNODB STATUS;

最低限見るべきポイントメモ

  • TRANSACTIONS
    → History list length と長時間トランザクション
  • LOG
    → redo log の詰まり具合
  • BUFFER POOL
    → Dirty Page、Pending writes、hit rate
  • ROW OPERATIONS
    → InnoDB 内部の詰まり具合

TRANSACTIONS(長時間トランザクション & 履歴の溜まり具合)

------------
TRANSACTIONS
------------
Trx id counter 493829303
Purge done for trx's n:o < 493829211
History list length 42

---TRANSACTION 493829298, ACTIVE 52 sec
5 lock struct(s), 10 row lock(s)
UPDATE big_table SET processed = 1 WHERE status = 'pending'
  • History list length
    • 100〜200 → 普通
    • 数千〜 → パージ遅延。長時間トランザクションの可能性
  • ACTIVE が長いトランザクション
    • 数秒〜数十秒 → よくある
    • 数分〜数時間 → だいたい何か詰まっている

LOG(redo log が詰まりそうか)

LOG
-------------------------------------
Log sequence number  225405840928
Last checkpoint at   225405700000
  • LSN – checkpoint の差 が log ファイル総容量に近づくと危険
  • 差が大きくなりすぎると、InnoDB は Dirty Page の強制 flush を始め、
    UPDATE/INSERT が急に遅くなる原因 になる

BUFFER POOL AND MEMORY(Dirty Page と I/O の詰まり)

BUFFER POOL AND MEMORY
-------------------------------------
Buffer pool size   2048000
Database pages     544290
Modified db pages  1120
Pending writes LRU 0, flush list 3
Buffer pool hit rate 999 / 1000
  • Modified db pages(Dirty Page)
    • Dirty 割合が 数%以下 → 健全
    • Dirty 割合が 高止まり(例:30〜50%) → 書き込みが追いついてない
  • Pending writes
    • 0〜数個 → 普通
    • ずっと 100 以上 → ディスク I/O が悲鳴
  • Buffer pool hit rate
    • 995/1000 以上 → ほぼメモリだけで動いている
    • 950/1000 を切る → バッファプール不足を疑う

ROW OPERATIONS(いまの負荷感)

ROW OPERATIONS
-------------------------------------
0 queries inside InnoDB, 2 queries queued
0.12 inserts/s, 0.30 updates/s, 10.30 reads/s
  • queries queued が増える
    → 何かのリソース待ち(ロック・I/O)が発生
  • 行ベースの秒間処理量をざっくり見ることで、
    「今負荷が高いか」だけ判断できる

まとめ

InnoDB は、メモリを中心に動くストレージエンジンで、ディスクはあくまで後追い。
メモリ上で最新の状態を保ち、ディスクへの書き込みは最適なタイミングで行われる仕組み。

また気づきがあれば追記していく予定です。

コメント

タイトルとURLをコピーしました