本番直前にシステムが「ダウン」した時の衝撃
6ヶ月前、ECサイトのフラッシュセールキャンペーンを運営していた際、私は冷や汗をかく経験をしました。ステージング環境では、レイテンシはわずか10〜20msと非常に安定していました。私は自信満々に上司に報告しました。「システムは余裕で耐えられますよ」と。
しかし、現実は甘くありませんでした。午前0時ちょうど, トラフィックは一気に20倍に跳ね上がりました。1,200万件のレコードを持つordersテーブルは「フリーズ」し始め、サーバーのCPU使用率は98%に達し、RAMは枯渇、そして大量のリクエストが504 Gateway Timeoutエラーを返しました。そこで得た教訓は非常に重いものでした。「機能が正しく動くこと」と「負荷に耐えられること」は別物であるということです。
なぜ手動テストでは勘違いが起きるのか?
最大の失敗は、MySQL WorkbenchでいくつかのEXPLAINを実行しただけで満足していたことです。自分一人でデータベースを「独占」してSQLを実行するのと、1秒間に500人が同時に「決済」ボタンをクリックするのとでは、状況が全く異なります。リソースの競合こそが真の敵なのです。
問題を分析した結果、3つの主な「犯人」が判明しました:
- Connection Overhead: 毎分2,000件の接続を開閉することで、RAMが急速に枯渇しました。
- Lock Contention: Updateコマンドが行レベルロック(row-level lock)を奪い合い、長い待ち行列が発生しました。
- Disk I/O: キャッシュが溢れ、MySQLは低速なハードディスクからデータを読み込まざるを得なくなりました。
ベンチマークツールの選定:強力なだけでなく、手軽さも重要
同じ過ちを繰り返さないために、私はテストツールを探し始めました。JMeterはクエリのクイックテストには重すぎました。Sysbenchは強力ですが、設定が複雑で環境構築に半日かかってしまいます。
最終的に選んだのは**mysqlslap**です。これはMySQLをインストールすると標準で付いてくるツールで、非常に軽量かつ実用的です。
5分でマスターするmysqlslap
mysqlslapを使えば、数百人のユーザーが同時にサーバーへクエリを「叩き込む」様子をシミュレートできます。サーバーがダウンする前に、どれくらいの負荷に耐えられるかを正確に把握できます。
1. 全体的な健康診断
データベースの準備なしでクイックテストを行うには、次のコマンドを使用します:
mysqlslap --user=root --password --auto-generate-sql --concurrency=100 --iterations=5
ここで、--concurrency=100は100人のユーザーが同時アクセスする状況をシミュレートしています。OSのバックグラウンドタスクによる誤差を排除し、正確な平均値を得るために5回(--iterations=5)繰り返します。
2. 実際のデータを用いたテスト
全体テストの後は、**Slow Query Log**からリソースを大量に消費しているクエリを抽出し、サーバーに負荷をかけます。例えば、production_copyデータベースで複雑なJOINクエリをテストする場合:
mysqlslap --user=root --password \
--concurrency=30 --iterations=3 \
--query="SELECT * FROM orders JOIN users ON orders.user_id = users.id WHERE orders.status = 'pending';" \
--create-schema=inventory_db
このコマンドにより、30人が同時にレポートを閲覧した際にシステムがラグを起こすかどうかを確認できます。
3. 混合負荷(読み取りと書き込み)のシミュレーション
実際には、閲覧(Read)だけのユーザーはいません。必ず購入(Write)するユーザーも存在します。私はこのシナリオを再現するためにmixedオプションをよく使います:
mysqlslap --user=root --password --concurrency=80 --iterations=5 \
--auto-generate-sql --auto-generate-sql-load-type=mixed
この時、mysqlslapはINSERTとSELECTを混在させます。これはテーブルロックの問題を発見するのに最適な方法です。
「数字」に騙されないための結果の読み方
実行後、実行時間の統計(Average, Minimum, Maximum)が表示されます。平均値だけを見るのは避けましょう。
同時接続数を50から100に増やしたときに、Average timeが0.5秒から5秒に跳ね上がった場合、それは危険信号です。サーバーがCPUの限界に達しています。
1,200万行のテーブルでの私の経験では、インデックスを追加した後、平均実行時間が3.2秒から0.15秒に短縮されました。10回のテストを経てこの数値が安定していることを確認して初めて、本番環境へのデプロイを決端しました。
深夜にデータベースをリストアせずに済むための注意点
mysqlslapの使用は諸刃の剣です。ユーザーが利用中の本番(Production)サーバーでこのツールを直接実行するのは絶対にやめてください。膨大な負荷がかかり、即座にWebサイトをダウンさせてしまう可能性があります。
必ず、同等のハードウェア構成を持つ複製(Clone)環境でテストしてください。手元のMacbook i7での結果と、月額10ドルの2 vCPUクラウドサーバーでの結果は全く異なります。
結論として、システムがダウンしないことを祈るのではなく、mysqlslapで積極的に「負荷をかけて」検証しましょう。データベースの最適化が成功することを願っています!

