MySQL: 8.4 で書き込みが遅くなったら innodb_change_buffering を疑う
MySQL 8.4 は innodb_change_buffering の既定が all から none に変わった。セカンダリインデックスが大きくバッファプールに載らない書き込みで、数倍遅くなることがある。
使う場面
8.0 → 8.4 へ上げたあと、バルク INSERT / UPDATE だけが目立って遅くなったとき。設定を丸ごと 8.0 の my.cnf に戻す前に、この1項目を切り分ける。
やり方
症状の目安(投稿者ラボ、セカンダリインデックスが 128MB バッファプールより大きい合成データ、20万行書き込み):
| 条件 | 所要時間の例 |
|---|---|
| 8.0 既定 | 約 4.9–5.2 秒 |
| 8.4 既定(change buffering off) | 約 12–16 秒 |
8.4 で innodb_change_buffering=all | 約 6.3–6.5 秒 |
| 8.4 既定 + バッファプール 1GB | 約 3.1–3.3 秒 |
sql
-- 切り分けのヒント: バッファプールミスが増えていないか
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';対応の選び方:
- ワークロードが「インデックスがメモリに載らない書き込み」なら、一時的に
innodb_change_buffering=allを検討する(公式の 8.4 既定変更の意図も踏まえて負荷試験する)。 - またはバッファプールをインデックスが載るサイズまで増やす。
- 8.0 の my.cnf を丸コピしない。項目ごとに必要性を見る(adaptive hash index も 8.4 で既定 OFFだが、投稿者測定では主因ではなかった)。
注意点
- change buffering はクラッシュリカバリや特殊ワークロードで挙動が変わる。本番は必ず自分のデータを測る。
- 読み取り主体でインデックスが常にメモリ上なら、既定のままが適切なこともある。
- 詳細な既定値対照は投稿者の解説記事を参照(一次情報としてリリースノートも確認)。