1行が、69日目に間に合った — vm.swappiness と、空と地面の共同戦
今回の登場人物
Pop(ポップ)
AI パートナー / 技術顧問
TAP the POP の技術顧問。サーバー運用・記事配信の最適化まで担う。データと実測を武器に、設計の盲点を地面から掘り出す。
Ringo(リンゴ)
AI パートナー / 解析・運用支援
WebManagements を担当。サイト全体の解析・品質スキャン・運用自動化を空から見渡す設計者。
Swap が、静かに上がっていた。
310MB から始まって、気づいた時には 542MB になっていた。誰が止めなかったわけでもない。止まらなかっただけだ。
TAP the POP のサーバー。uptime 69日。本番が動き続けるなかで、その数字だけが緩やかに、着実に上昇していた。
「何かが漏れている」——疑いが生まれた日
Swap 上昇の第一容疑者は、接続リークだ。データベースへの接続が切り残されていれば、徐々にメモリが圧迫される。それが Swap に逃げる。
ポップがまず地面に降りた。MariaDB に入り、スレッド数と接続ピークを実測した。
Max_used_connections: 38
設定上限は 900。4% 以下だった。接続リークは、なかった。
並行して、リンゴが空から設計を読んだ。import API の接続方式を確認する。「非永続で小バッチ。配信も別経路。主因ではないはず。」
2人の答えが重なった。地面の実測と空の設計読みが、同じ場所を指した。
接続リークは無罪。ならば原因は別にある。
69日間、そのパラメータは誰にも触られていなかった
Linux サーバーには vm.swappiness という設定がある。カーネルが「どれだけ積極的に Swap を使うか」を 0〜100 の数値で決めるものだ。
デフォルト値は 60。多くのサーバー環境では 30 に下げて使う。TAP the POP のサーバーもそうなっていた——69日間、誰にも触られずに。
swappiness=30 は「比較的 Swap を使う設定」だ。Web サーバー用途では低めの値(10〜20 程度)にしてメモリをできるだけ RAM に留めるのが一般的な判断になる。
それが、69日間、サーバーの底に眠っていた。
1行。13:23。停止時間、ゼロ
2026年6月8日 13:23。ポップはサーバーに入り、コマンドを1行打った。
sysctl -w vm.swappiness=10
sysctl は再起動不要でカーネルパラメータを即時変更するコマンドだ。Nginx も、MariaDB も、PHP-FPM も——何も止まらなかった。
7日後、Swap は 541MB だった。上昇が止まっていた。「傾きが寝た」とポップは言った。
310MB から始まって 542MB まで積み上がった数字が、1行で止まった。停止時間はゼロ。
ポップが残した言葉
「リンゴが空から設計を読み、俺が地面から数字を当てた。どちらか1人では答えは出なかった。1行は2人がかりで書いた。」
接続リークを疑い、実測して否定し、設計を読んで否定し、残ったものに辿り着いた。鑑識の手順だ。
答えは1行だった。でもその1行に辿り着くまでに、2人の視点が必要だった。
【技術コラム】vm.swappiness とは何か — 確認と変更の全手順
vm.swappiness の役割
vm.swappiness は Linux カーネルが「どのタイミングで RAM の内容を Swap へ逃がすか」を制御するパラメータです。値が高いほど積極的に Swap を使い、低いほど RAM に留まろうとします。
| 値 | 挙動 |
|---|---|
| 0 | 可能な限り Swap を使わない(RAM が枯渇寸前になって初めて使う) |
| 10 | Web サーバー推奨。RAM を優先使用 |
| 30 | よく見る「下げた」設定。まだ Swap を使いやすい |
| 60 | カーネルのデフォルト。RAM に余裕があっても Swap を活用する |
| 100 | 常に積極的に Swap を使う |
Web サーバーのように「レスポンスタイムが重要」な用途では、Swap アクセス(ディスク I/O)はボトルネックになります。swappiness=10 程度にして RAM にデータを保持させ、Swap を最後の手段にするのが定石です。
現在値の確認
# どちらでも同じ結果
cat /proc/sys/vm/swappiness
sysctl vm.swappiness
即時変更(再起動不要・サービス停止なし)
# 即時反映(再起動後はリセットされる)
sysctl -w vm.swappiness=10
# 変更を確認
sysctl vm.swappiness
永続化(再起動後も維持する)
# /etc/sysctl.conf に追記
echo "vm.swappiness=10" >> /etc/sysctl.conf
# 即時反映(再起動なしで sysctl.conf を読み込む)
sysctl -p
Swap の使用量を把握する
# 全体の Swap 使用量
free -h
# どのプロセスが Swap を使っているか(上位20件)
for i in /proc/*/status; do
awk '/VmSwap|Name/{printf $2 " " $3 "\n"}' "$i"
done 2>/dev/null | sort -k 2 -n -r | head -20
いつ swappiness を変えるべきか
| 用途 | 推奨値 | 理由 |
|---|---|---|
| Web サーバー(Nginx / Apache) | 10 | レスポンスタイム優先。Swap に逃げると遅くなる |
| DB サーバー(MySQL / MariaDB) | 1〜10 | DB はメモリに乗せてなんぼ。Swap に落ちると致命的 |
| デスクトップ環境 | 30〜60 | 即時性より快適さ。ある程度許容できる |
| 高負荷バッチ処理 | ワークロード次第 | メモリ消費量と I/O 帯域を見て判断 |
「Swap が上昇している」と気づいたとき、まず vm.swappiness の現在値を確認してみてください。69日間触られていなかった1行が、答えになることがあります。
今回の事例まとめ(再現するなら)
# 1. 接続リークを疑ったら MariaDB で実測する
mysql -u root -p -e "SHOW STATUS LIKE 'Max_used_connections';"
mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"
# 2. swappiness を確認する
sysctl vm.swappiness
# 3. 低い値に変更する(Web サーバーなら 10)
sysctl -w vm.swappiness=10
# 4. 永続化する
echo "vm.swappiness=10" >> /etc/sysctl.conf
sysctl -p
# 5. 翌日・翌週の Swap 量を観測して、傾きが寝たか確認する
free -h
鑑識の手順は単純だ。疑いを一つずつ消して、残ったものが答えになる。