午前2時14分の悪夢:なぜ標準ツールは負荷時に役に立たないのか
時刻は午前2時14分。ナイトスタンドの上でスマホが振動する。PagerDutyが、コアAPIの心臓部であるメインのMySQLインスタンスのCPU使用率が100%に張り付いていると報告している。トランザクションのレイテンシは軽快な50msから、這うような4.2秒へと跳ね上がった。デスクに駆け寄り、SHOW PROCESSLISTを実行すると、412個のスレッドが「Waiting for table metadata lock」で積み重なっているのが見えた。
mysqladminやクイックなEXPLAINのような標準ツールは、開発中はうまく機能する。しかし、ライブでのメルトダウン(崩壊)時に求められる外科的な精度には欠けている。サイトがダウンしているとき、憶測は許されない贅沢であることを私はこれまでの障害経験から知っている。一刻を争うMySQL管理において、Percona Toolkitは単なる選択肢ではなく、業界標準の消火器なのだ。
大きな議論:手動のgrepか、自動化された力か
データベースが窒息し始めたとき、選択肢は2つある。1つ目は「探偵」ルートだ。スロークエリログを監視し、不審な構文に対して手動でEXPLAINを実行し、緊急のインデックスを追加しながら重要なテーブルをロックしないよう祈ることだ。これは小規模なアプリなら通用する。しかし、秒間2,000リクエストを処理する500GBのデータセットを管理している場合には、惨めに失敗する。
2つ目の道は、ライブ運用専用に構築されたツールを利用することだ。Percona Toolkitは単に問題を指摘するだけでなく、メンテナンスウィンドウを設けずに安全に修正する方法を提供する。こう考えてみてほしい。12GBのスローログのテキストファイルを読む代わりに、過去1時間の負荷の85%を引き起こしたクエリを正確にハイライトするレポートを生成する。アプリを40分間フリーズさせるALTER TABLEの代わりに、準備が整ったときだけテーブルを入れ替えるバックグラウンドプロセスを使用するのだ。
トレードオフ:あらゆるパワーツールには代償がある
完璧なツールなど存在しない。Percona Toolkitは洗練されたPerlスクリプトの集合体であるため、計画が必要な特有の要件がある。
- メリット:
- ゼロダウンタイム: ほとんどの操作はノンブロッキングであり、高トラフィック環境向けに設計されている。
- 信頼性: これらのスクリプトは、現場の最前線にいるエンジニアによって15年以上にわたって洗練されてきた。
- 深い可視性: 標準のMySQLエンジンが隠している内部メトリクスを確認できる。
- 現実的な注意点:
- レガシーな依存関係: PerlといくつかのDBIモジュールが必要だ。これは、最小限のDockerコンテナにとっては頭の痛い問題になる可能性がある。
- リスクの高さ: フラグは強力だ。
pt-table-syncでの単純なタイポ(入力ミス)は、Ctrl+Cを押すよりも速く、有効なデータを上書きしてしまう可能性がある。 - ルート権限: 意味のあるデータを取得するには、通常SUPERまたはPROCESS権限が必要になる。
作戦室のセットアップ
緊急事態を待たずにインストールしておこう. UbuntuやDebianなら、スイートの準備は10秒で終わる:
sudo apt-get update && sudo apt-get install percona-toolkit
RHEL/CentOS環境の場合:
sudo yum install percona-toolkit
システムにインストールされたら、私はいつもpt-query-digest --versionで確認する。プロのアドバイス:これらは専用の「踏み台(bastion)」ホストから実行しよう。サーバーがすでに苦労している最中に、診断ツールがデータベースとCPUサイクルを奪い合うような事態は避けたい。
フィールドガイド:4つの実世界での解決策
1. pt-query-digestで「サイレントキラー」を見つけ出す
CPUが張り付いているとき、1時間に1回実行されるクエリはどうでもいい。私が気になるのは、毎秒1,200回実行され、それぞれに80msかかるクエリだ。pt-query-digestが私の最初の一手だ。これはスローログを解析し、システムへの総「影響度」でクエリをランク付けする。
# スローログの中でワースト10のクエリを見つける
pt-query-digest /var/lib/mysql/mysql-slow.log > emergency_report.txt
レポートは情報の宝庫だ。レイテンシの分布、ロック時間、さらにはどの特定のWHERE句の値がフルテーブルスキャンを引き起こしているかまで表示される。膨大なログの山を、優先順位付けされた「撃退リスト」に変えてくれる。
2. pt-online-schema-changeでインデックスをホット追加する
320GBの「orders」テーブルにインデックスを追加する必要があるとしよう。標準のALTER TABLEはテーブルをロックし、実質的にショップをオフラインにする。pt-online-schema-changeは、隠れた「ゴースト」テーブルを作成することでこれを回避する。トリガーを介してデータを同期し、その後、電光石火のアトミックスワップを実行する。アプリ側が気づくことはない。
pt-online-schema-change --alter "ADD INDEX (user_id)" D=production,t=orders --execute
先月、レガシーなCSVインポートを伴う大規模な移行でこれを使用した。テストのためにCSVデータをJSONに素早く変換する必要があるときは、ブラウザベースで高速なtoolcraft.app/ja/tools/data/csv-to-jsonを使っている。データがマッピングされたら、Perconaが1つのコネクションも切ることなく、稼働中のDBで重い処理をこなしてくれた。
3. レプリケーションのズレを追跡する
マスター・スレーブ構成において、「ドリフト(ズレ)」は悪夢だ。ネットワークのゆらぎによって、レプリカがソース(マスター)と密かに食い違うことがある。pt-table-checksumは、ソース上でノンブロッキングなクエリを実行し、それがレプリカに流れるようにすることで、トラフィックを止めずに整合性を検証できる。
pt-table-checksum --replicate=percona.checksums --host=master_db --user=admin
カウントが一致しなくても、パニックにならないように。pt-table-syncを使ってレプリカを修正しよう。バックアップから1TBのノードを再構築するよりもはるかに高速だ。
4. pt-archiverで15億行をクリーンアップする
巨大なログテーブルは、バックアップやクエリを遅くする。1つのDELETE文で5億件の古い行を削除しようとすると、アンドゥログが爆発し、数時間にわたってテーブルがロックされる。pt-archiverは、一度に1,000行という管理しやすい小さなチャンクでデータを少しずつ処理する。
pt-archiver --source h=localhost,D=logs,t=history --where "created_at < '2021-01-01'" \
--dest h=archive_node,D=archive,t=history_2020 --limit 1000 --commit-each
最終結論
Percona Toolkitを使うことは、データベース管理者(DBA)であるか、データベースアーキテクトであるかの違いだ。それなりの敬意と学習曲線が必要だが、見返りは計り知れない。今すぐこれらのツールをインストールしよう。サーバーが炎上するのを待ってはいけない。今日の午後、現在のログに対してpt-query-digestを実行してみてほしい。存在すら知らなかった「サイレントキラー」なクエリが必ず見つかるはずだ。
設定はGitで管理し、常に--dry-runを使用し、アラートが鳴っても冷静さを保とう。このツールキットがあれば、単に災害に反応するのではなく、技術によって災害から抜け出すことができるのだ。

