LinuxのI/Oスケジューラを確認・変更する方法|mq-deadline・BFQのSSD/HDD別の推奨設定とudev永続化

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Linuxtips > LinuxのI/Oスケジューラを確認・変更する方法|mq-deadline・BFQのSSD/HDD別の推奨設定とudev永続化
「データベースサーバーを本番環境に移設したのにI/Oが改善しない」「SSDに換装したはずなのに応答速度がHDD時代と変わらない」——そういった経験をしているエンジニアは少なくない。

原因の一つとして見落とされがちなのが、LinuxカーネルのI/Oスケジューラの設定だ。I/Oスケジューラはカーネルがディスクへの読み書き要求をどの順序・方式で処理するかを決める仕組みで、SSDとHDDでは最適解が大きく異なる。カーネル5.0以降ではマルチキューアーキテクチャ(blk-mq)が標準となり、使えるスケジューラの種類も変化している。

この記事では、現在のI/Oスケジューラを確認する方法から始め、none・mq-deadline・BFQを用途別に切り替える手順、udev rulesで設定を永続化する方法、データベース・仮想化サーバー向けの推奨設定まで解説する。RHEL 9系~Rocky Linux 9・Ubuntu 24.04 LTSを想定環境として説明する。

この記事のポイント

・現在のスケジューラは cat /sys/block/<デバイス>/queue/scheduler で確認できる
・SSD/NVMeには none か mq-deadline、HDDには bfq が基本方針
・echo コマンドで即時変更できるが再起動で消えるため udev rules で永続化する
・DBサーバーは mq-deadline(SATA SSD)または none(NVMe)が推奨


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

I/Oスケジューラとは何か、なぜ重要なのか

アプリケーションがファイルを読み書きするとき、I/O要求はすぐにディスクへ送られるわけではない。カーネルはいったん要求をキューに溜め込み、I/Oスケジューラが処理順を決定してからデバイスドライバに渡す。

この処理順の決定がパフォーマンスに大きく影響する理由は、HDDとSSDの物理特性の違いにある。

・HDDの場合:物理的なヘッドが移動してデータを読み書きするため、ヘッド移動距離を最小化する「シーク最適化」が効果的だ。バラバラなアドレスのI/O要求をアドレス順に並べ替えることで、スループットが大幅に向上する。
・SSD・NVMeの場合:物理的なヘッドが存在せず、どのアドレスも均一速度でアクセスできる。そのため複雑なスケジューリングは不要で、スケジューラのオーバーヘッド自体がボトルネックになる可能性がある。

カーネル5.0以降では、旧来の cfq(Completely Fair Queuing)は廃止された。現行の主要スケジューラは none・mq-deadline・bfq・kyber の4種類だ(カーネルのビルド構成によって利用できるスケジューラは異なる)。

I/Oスケジューラの設定を意識するのは特に、ストレージを換装したとき・本番サーバーのパフォーマンスチューニングをするとき・新規サーバーを構築するときだ。ディストリビューションのデフォルト設定が用途に合っているとは限らない。

現在のI/Oスケジューラを確認する方法

1. ブロックデバイスの一覧を確認する

まず lsblk でシステムのブロックデバイスを確認する。-d オプションでディスク単体のみ表示し、ROTA 列でHDD(1)かSSD(0)かを判定できる。

$ lsblk -d -o NAME,TYPE,SIZE,ROTA

出力例(環境により異なります):

NAME TYPE SIZE ROTA sda disk 500G 1 sdb disk 250G 0 nvme0n1 disk 500G 0

ROTA=1 がHDD、ROTA=0 がSSD・NVMeだ。

2. スケジューラの現在設定を確認する

/sys/block/<デバイス名>/queue/scheduler を読むと、現在のスケジューラと対応しているスケジューラの一覧を確認できる。現在有効なスケジューラは [ ](角括弧)で囲まれている。

# SATAディスクの例 $ cat /sys/block/sda/queue/scheduler # NVMeディスクの例 $ cat /sys/block/nvme0n1/queue/scheduler

出力例(環境により異なります):

# SATAディスク(mq-deadlineが有効) [mq-deadline] none bfq # NVMeディスク(noneが有効) [none] mq-deadline

3. 全デバイスをまとめて確認する

複数のディスクが存在する場合は、シェルのforループで一括確認すると効率的だ。

$ for dev in /sys/block/*/queue/scheduler; do echo "$dev: $(cat $dev)" done

出力例(環境により異なります):

/sys/block/sda/queue/scheduler: [mq-deadline] none bfq /sys/block/nvme0n1/queue/scheduler: [none] mq-deadline

主要I/Oスケジューラの特徴と使い分け

現行カーネルで利用できる主要なスケジューラの特徴を整理する。

・none(noop):スケジューリングを行わず、キューに届いた順にそのままデバイスに送る。NVMeのような超高速デバイスでは、スケジューラのオーバーヘッドを排除することで最大性能を引き出せる。NVMeのデフォルトとして多くのディストリビューションで採用されている。
・mq-deadline:I/O要求に有効期限(デッドライン)を設定し、期限切れになりそうな要求を優先して処理する。書き込みの「スタベーション」(長時間待たされる現象)を防ぐ効果があり、データベースサーバー(MySQL・PostgreSQL)との相性がよい。SATA SSDのデフォルト値としてよく使われる。
・bfq(Budget Fair Queueing):プロセスごとに帯域を公平に割り当てるスケジューラ。大量のランダムI/Oが発生するHDD環境や、複数プロセスがI/Oを競合するファイルサーバー環境に向く。
・kyber:低レイテンシを優先するスケジューラ。SSDでリアルタイム性が求められるケースを対象に設計されているが、bfqやmq-deadlineと比べて採用実績は限られる。

スケジューラ 適したデバイス 主な特徴 代表的な用途
none NVMe SSD パススルー、最小オーバーヘッド 高速DB、NVMe搭載サーバー
mq-deadline SATA SSD デッドライン保証、書き込みスタベーション防止 データベースサーバー(SATA SSD)
bfq HDD プロセスごとの帯域公平分配 ファイルサーバー、汎用HDD構成
kyber SSD 低レイテンシ優先 リアルタイム性が必要なケース

I/Oスケジューラを一時的に変更する方法

スケジューラの変更は /sys/block/<デバイス>/queue/scheduler に echo で書き込むことで即時反映できる。ただし再起動で消える一時的な変更である点に注意が必要だ。本番サーバーで本格適用する前に、まずこの方法で動作を確認し、問題がなければ後述のudev rulesで永続化するのが安全な手順だ。

1. 変更前の確認

$ cat /sys/block/sda/queue/scheduler [mq-deadline] none bfq

2. スケジューラを変更する

# HDD(sda)をbfqに変更する $ echo bfq > /sys/block/sda/queue/scheduler # SATA SSD(sdb)をnoneに変更する $ echo none > /sys/block/sdb/queue/scheduler

3. 変更を確認する

$ cat /sys/block/sda/queue/scheduler none [bfq] mq-deadline

[bfq] と角括弧で囲まれていれば変更は成功だ。Invalid argument が返る場合は、デバイス名のタイプミスか、そのスケジューラがカーネルで利用不可能な状態にある。

udev rulesで永続化する方法

再起動後も設定を維持するには、udev rules(/etc/udev/rules.d/ 配下のルールファイル)に設定を書く。udevはカーネルがデバイスを検出するたびにルールを評価するため、起動時に自動的にスケジューラが設定される。

1. ルールファイルを作成する

ファイル名は任意だが、数字が小さいほど先に評価される慣習があるため 60-scheduler.rules あたりが一般的だ(60番台はハードウェア関連の設定によく使われる)。

$ sudo vi /etc/udev/rules.d/60-scheduler.rules

2. ルールを記述する

HDDとSSD(SATA)、NVMeに対してそれぞれ条件を書く。ATTR{queue/rotational}=="1" がHDD、=="0" がSSD/NVMeを示す。

# hdd (rotational==1) → bfq ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq" # sata ssd (rotational==0) → mq-deadline ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline" # nvme → none ACTION=="add|change", KERNEL=="nvme[0-9]*n[0-9]*", ATTR{queue/scheduler}="none"

3. udev rulesを反映させる

ファイルを保存したら、実行中のシステムに即座に反映させる。

# ルールをリロード $ sudo udevadm control --reload-rules # 既存デバイスにルールを再適用 $ sudo udevadm trigger --type=devices --action=change

4. 反映を確認する

$ cat /sys/block/sda/queue/scheduler

ルール構文のデバッグには udevadm test が便利だ(実際の変更は行わない)。

$ sudo udevadm test /sys/block/sda 2>&1 | grep scheduler

用途別の推奨設定

データベースサーバー(MySQL・PostgreSQL)

データベースはランダムI/Oが多く、書き込み完了の保証(fsync)を多用する。スケジューラの選択がDB性能の安定に直結する。

・SATA SSD搭載サーバー:mq-deadline を推奨。書き込みのスタベーション防止と適度なI/O優先度管理が、DB運用の安定化に寄与する。
・NVMe SSD搭載サーバー:none を推奨。NVMeのパフォーマンスを最大限に引き出すには、スケジューラのオーバーヘッドを排除するのが基本的な方針だ。

KVM仮想化ホスト

KVM上の仮想ディスク(virtio-blk)は、ゲストOS側で独自のI/OスタックとスケジューラがI/O要求をさらに最適化する。ホスト側でも重複してスケジューリングすると二重オーバーヘッドになるため、ホスト側の物理ディスクスケジューラは none または mq-deadline に設定するのが一般的だ。

汎用ファイルサーバー・HDD構成

複数のユーザー・プロセスがHDDへ同時アクセスする環境では、bfq が帯域を公平に分配し、特定プロセスだけI/Oを占有する事態を防いでくれる。NASやバックアップサーバーにHDDを使う場合はbfqが基本の選択肢になる。

I/Oの変化をiotopで確認する方法

スケジューラを変更した前後で効果を確認するには、iotop や iostat が役立つ。

iotop はプロセス別のディスクI/Oをリアルタイムで表示するツールだ。

# I/Oが発生しているプロセスだけ表示する(-oオプション) $ sudo iotop -o

iostat はデバイス単位のI/O統計を確認する。await(I/O要求の平均待ち時間)と %util(デバイスの使用率)が主要な指標だ。スケジューラ変更後に同一ワークロードを実行し、await の変化を比較することでチューニング効果を客観的に評価できる。

# 1秒ごとにデバイス詳細を表示 $ iostat -dx 1

トラブルシュート

指定したスケジューラが設定されない場合

echo mq-deadline > /sys/block/sda/queue/scheduler を実行しても Invalid argument エラーが出る場合は、そのスケジューラが利用できない状態にある。

まず cat /sys/block/sda/queue/scheduler で列挙されているスケジューラ名を確認する。そこに候補がなければ、カーネルにそのスケジューラモジュールが組み込まれていないか、当該デバイスが対応していない。NVMeの場合、ディストリビューションによっては mq-deadline しか選べない構成もある。

再起動後に設定が消える場合

udev rules を作成したにもかかわらず設定が消える場合は、以下を確認する。

・/etc/udev/rules.d/60-scheduler.rules のファイルが存在するか
・ルール構文にタイポがないか(ATTR{queue/scheduler}="bfq" の引用符は二重引用符)
・同じデバイスに対して競合するルールが他のファイルに存在しないか(ls /etc/udev/rules.d/ で確認)

ルールの評価結果を確認するには udevadm test を使う。

仮想マシンのディスク(/dev/vdaなど)の場合

KVM仮想マシンのゲストOSでは、仮想ディスク(/dev/vda など)に対して選択できるスケジューラが [none] だけに制限されていることが多い。

$ cat /sys/block/vda/queue/scheduler

出力例(環境により異なります):

[none]

これはゲストI/Oの最適化をホスト側のハイパーバイザーに委ねる設計によるものだ。変更できなくても問題はなく、ゲストOSとしては正常な状態だ。

本記事のまとめ

やりたいこと コマンド/設定
現在のスケジューラを確認する cat /sys/block/sda/queue/scheduler
全デバイスのスケジューラを一覧確認する for dev in /sys/block/*/queue/scheduler; do echo "$dev: $(cat $dev)"; done
スケジューラを一時的に変更する echo mq-deadline > /sys/block/sda/queue/scheduler
udev rulesで永続化する /etc/udev/rules.d/60-scheduler.rules にATTR設定を記述
udev rulesを即座に反映させる sudo udevadm control --reload-rules && sudo udevadm trigger --type=devices --action=change
I/Oをプロセス別に確認する sudo iotop -o
デバイス別I/O統計を確認する iostat -dx 1

I/Oスケジューラの最適化はLinuxサーバーのパフォーマンスチューニングの一手段に過ぎない。実際の本番運用では、ストレージ設定・ネットワーク設定・セキュリティ設定・障害対応など、体系的な知識と実践スキルが求められる。現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Linux Master Pro Seminar では20年以上の実務経験をもとにしたサーバー構築・運用の知識をハンズオン形式で習得できる。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。