そう感じていませんか。MySQLのパフォーマンス問題の多くは、インストール直後のデフォルト設定のままmy.cnfが放置されていることが原因です。デフォルト値は非常に保守的な設定になっており、現代のサーバーのメモリを全く活かしきれていません。
この記事では、my.cnfチューニングの核心であるinnodb_buffer_pool_sizeとmax_connectionsの正しい設定方法を、RAM 4GB・8GB・16GBの3パターンで具体的な数値を交えて解説します。チューニング後の効果検証方法(SHOW STATUS)、よくある設定ミスと対処法も合わせて解説しますので、MySQL/MariaDB両方の実務に対応できます。
この記事のポイント
・innodb_buffer_pool_sizeは「空きRAMの70~80%」が実務のセオリー
・max_connectionsはper-threadバッファと掛け算で上限メモリを算出して決める
・MySQL 8.0ではquery_cache_sizeは廃止。MariaDBとの違いに注意
・SHOW STATUSのヒット率でバッファプールの効果を定量的に確認できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
my.cnfとは何か:MySQLの動作を決める設定ファイルの基本
my.cnf(Windowsではmy.ini)は、MySQLおよびMariaDBの動作を制御するメインの設定ファイルです。サーバーの起動時に読み込まれ、メモリ割り当て・接続数・ログ設定・ストレージエンジンの動作など、パフォーマンスに直結するほぼすべての設定が記述されています。MySQLのデフォルト設定は非常に保守的で、数百MBのメモリしか使わないように設計されています。RAM 8GBや16GBのサーバーで何年もデフォルトのまま動かしているケースを現場で何度も見てきましたが、これでは宝の持ち腐れです。適切なチューニングを施すだけで、クエリ応答速度が数倍から数十倍改善することも珍しくありません。
1. my.cnfが読み込まれる順序を確認する
MySQLはmy.cnfを複数の場所から順番に読み込みます。後で読み込まれたファイルの設定が優先されるため、どのファイルが実際に有効になっているかを把握しておくことが重要です。読み込み順序を確認するには、次のコマンドを実行してください。
# MySQLが参照する設定ファイルの順序を確認する $ mysql --help | grep -A 1 "Default options" Default options are read from the following files in the given order: /etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf # MariaDBの場合 $ mariadbd --help --verbose 2>&1 | grep "Default options" -A 1 Default options are read from the following files in the given order: /etc/my.cnf /etc/mysql/my.cnf /etc/my.cnf.d/mariadb-server.cnf ~/.my.cnf
/etc/my.cnfが主流ですが、Ubuntu/Debianでは/etc/mysql/mysql.conf.d/mysqld.cnfに分割されている場合があります。2. [mysqld]セクションの基本構造
my.cnfはINIファイル形式で、セクションごとに設定が分かれています。MySQLサーバー本体の設定は[mysqld]セクションに記述します。クライアントツールやシェルの設定は別のセクションになります。# /etc/my.cnf の基本構成例 [mysqld] # 基本設定 user = mysql datadir = /var/lib/mysql socket = /var/lib/mysql/mysql.sock pid_file = /var/run/mysqld/mysqld.pid # 文字コード(MySQL 8.0ではutf8mb4がデフォルト) character-set-server = utf8mb4 collation-server = utf8mb4_general_ci # ネットワーク bind-address = 127.0.0.1 port = 3306 # エラーログ log_error = /var/log/mysqld.log [client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4
# RHEL/CentOS/Rocky Linux の場合 $ sudo systemctl restart mysqld # Ubuntu/Debian の場合 $ sudo systemctl restart mysql # MariaDB の場合(どちらのOSでも) $ sudo systemctl restart mariadb # 起動状態の確認 $ sudo systemctl status mysqld
innodb_buffer_pool_sizeの正しい決め方:実メモリから計算する
MySQLのパフォーマンスチューニングで最も効果が大きいパラメータがinnodb_buffer_pool_sizeです。このパラメータはInnoDBストレージエンジンがデータとインデックスをキャッシュするためのメモリ領域のサイズを決定します。ここを適切に設定するだけで、多くの現場では劇的な速度改善が得られます。理由はシンプルです。ディスクI/Oとメモリアクセスの速度差は約1,000倍以上。よく使われるデータがバッファプール内に収まっていれば、SQLクエリのほとんどはメモリ内で完結します。
1. デフォルト値の問題点
デフォルト値はMySQL 5.6以前が8MB、MySQL 5.7以降が128MBです。現代のサーバーにとっては非常に小さい値です。まず現在の設定値を確認しましょう。
# 現在のinnodb_buffer_pool_sizeを確認する mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; +-------------------------+-----------+ | Variable_name | Value | +-------------------------+-----------+ | innodb_buffer_pool_size | 134217728 | +-------------------------+-----------+ 1 row in set (0.00 sec) # 134217728 バイト = 128MB(MySQL 5.7以降のデフォルト値) # RAM 8GBのサーバーでこの値のままでは明らかに設定不足
2. RAM別の推奨値(4GB・8GB・16GB)
MySQLを専用で動かすサーバーの場合、空きRAMの70~80%をinnodb_buffer_pool_sizeに割り当てるのが実務のセオリーです。Webアプリケーション(Apache・Nginx・PHP等)と同居する場合は50~60%を目安にします。・RAM 4GB の場合: 2G~2.5G(専用DBサーバー)/ 1.5G(Webアプリと同居)
・RAM 8GB の場合: 5G~6G(専用DBサーバー)/ 3G~4G(Webアプリと同居)
・RAM 16GB の場合: 10G~12G(専用DBサーバー)/ 7G~8G(Webアプリと同居)
以下はRAM 8GBのサーバーでWebアプリケーションと同居する構成の設定例です。
# RAM 8GB、Webアプリと同居する構成の設定例 [mysqld] # InnoDBバッファプール(RAMの約50%) innodb_buffer_pool_size = 4G # コメントアウト例: RAM別の参考値 # RAM 16GBの専用DBサーバーの場合 # innodb_buffer_pool_size = 12G # RAM 4GBの小規模サーバーの場合 # innodb_buffer_pool_size = 2G
3. innodb_buffer_pool_instancesの設定(1GB超の場合)
innodb_buffer_pool_sizeが1GBを超える場合は、innodb_buffer_pool_instancesを設定してバッファプールを複数のインスタンスに分割することが推奨されます。これにより並列アクセス時のロック競合が減少します。MySQL 5.7.8以降ではバッファプールが1GB以上の場合にデフォルトで8が設定されますが、明示的に指定することで意図を明確にできます。
# innodb_buffer_pool_size が 4G の場合: 4インスタンス(各1GB) [mysqld] innodb_buffer_pool_size = 4G innodb_buffer_pool_instances = 4 # innodb_buffer_pool_size が 12G の場合: 8インスタンス(各1.5GB) # innodb_buffer_pool_size = 12G # innodb_buffer_pool_instances = 8 # 確認コマンド # mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';
max_connectionsの適切な値:同時接続数とメモリの関係
max_connectionsを大きくすれば「接続エラー」は減りますが、メモリ不足でサーバーがクラッシュするリスクが生まれます。適切な値を決めるには、1接続あたりのメモリ消費量を計算する必要があります。1. max_connectionsとper-threadバッファの関係
MySQLは接続ごとにスレッドを割り当て、各スレッドは複数のバッファを専有します。主なper-threadバッファは以下の通りです。・sort_buffer_size:ソート操作用バッファ(デフォルト256KB)
・read_buffer_size:シーケンシャルスキャン用バッファ(デフォルト128KB)
・read_rnd_buffer_size:ランダム読み取り用バッファ(デフォルト256KB)
・join_buffer_size:JOINクエリ用バッファ(デフォルト256KB)
・thread_stack:スタックサイズ(デフォルト1MB)
デフォルト設定では1接続あたり最低でも2MB程度消費します。最大接続数まで接続が張られた場合の必要メモリは次の計算式で算出します。
# 最大メモリ使用量の概算計算式 # 必要メモリ = innodb_buffer_pool_size + (per-thread_buffers x max_connections) # per-thread_buffers = sort_buffer_size + read_buffer_size + read_rnd_buffer_size # + join_buffer_size + thread_stack # = 256KB + 128KB + 256KB + 256KB + 1024KB # = 約 2MB(デフォルト設定の場合) # RAM 8GB、innodb_buffer_pool_size=4GB の場合 # 残りRAM = 8GB - 4GB = 4GB(OS・その他プロセスを除くと実質2GB程度) # 安全なmax_connections上限 = 2GB / 2MB = 1000 # ただし現実的な上限は 200~300 程度(安全マージンを確保する)
2. 現在の同時接続数の実績を確認する
max_connectionsを設定する前に、現在の最大同時接続数の実績を確認しましょう。過去の最大値はMax_used_connectionsで取得できます。# 過去の最大同時接続数を確認する(サーバー起動後の累積最大値) mysql> SHOW GLOBAL STATUS LIKE 'Max_used_connections'; +----------------------+-------+ | Variable_name | Value | +----------------------+-------+ | Max_used_connections | 47 | +----------------------+-------+ # 現在の接続数を確認する(リアルタイム) mysql> SHOW GLOBAL STATUS LIKE 'Threads_connected'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Threads_connected | 12 | +-------------------+-------+ # max_connections の目安 = 実績値の1.5~2倍 # 上の例では47の1.5倍 = 71 → 余裕を見て100程度が適切
3. RAM別のmax_connections推奨値と設定例
・RAM 4GB(innodb_buffer_pool_size=2GB): 100~150・RAM 8GB(innodb_buffer_pool_size=4GB): 200~300
・RAM 16GB(innodb_buffer_pool_size=10GB): 400~500
# RAM 8GB、Webアプリと同居する構成の設定例 [mysqld] innodb_buffer_pool_size = 4G max_connections = 200 # per-threadバッファをデフォルト値で明示する(意図を記録する) sort_buffer_size = 256K read_buffer_size = 128K read_rnd_buffer_size = 256K join_buffer_size = 256K thread_stack = 1M # 接続タイムアウト設定 wait_timeout = 600 interactive_timeout = 600
Linux無料マニュアルを受け取る >>
その他の重要パラメータ(innodb_log_file_size / query_cache_size / slow_query_log)
innodb_buffer_pool_sizeとmax_connections以外にも、実務で押さえておくべき重要な設定があります。1. innodb_log_file_size(REDOログのサイズ)
innodb_log_file_sizeは、InnoDBのREDOログファイルのサイズを設定します。この値が小さすぎると、バッファプールのデータを頻繁にディスクにフラッシュ(書き出し)する必要が生じ、書き込みパフォーマンスが低下します。一般的には、innodb_buffer_pool_sizeの25%程度を目安にします。ただし、MySQL 8.0.30以降はinnodb_redo_log_capacityという変数に統合されたため注意が必要です。
# MySQL 5.7 の設定例 [mysqld] innodb_log_file_size = 256M # buffer_pool_size(4G)の約6%~25% innodb_log_buffer_size = 16M # MySQL 8.0.30以降: innodb_redo_log_capacity で総容量を指定する # innodb_redo_log_capacity = 2G # innodb_log_file_size は廃止(設定しない) # MariaDB 10.x: MySQL 5.7と同様の変数名が使える # innodb_log_file_size = 256M # 現在値を確認する # mysql> SHOW VARIABLES LIKE 'innodb_log_file_size';
2. slow_query_logの設定
slow_query_logは、実行に時間がかかったSQLクエリをログファイルに記録する機能です。チューニングの効果測定と問題クエリの特定に不可欠です。本番環境では必ず有効にしておきましょう。特にチューニング直後はどのクエリが遅いかを特定するために必須の設定です。
# スロークエリログの設定 [mysqld] slow_query_log = ON slow_query_log_file = /var/log/mysql/slow.log long_query_time = 1 # long_query_time: 1秒以上かかったクエリを記録する # 0に設定すると全クエリを記録(チューニング調査時のみ推奨) log_queries_not_using_indexes = ON # インデックスを使っていないクエリも記録する # ログディレクトリを作成してMySQLに書き込み権限を付与する # $ sudo mkdir -p /var/log/mysql # $ sudo chown mysql:mysql /var/log/mysql # mysqldumpslow コマンドでスロークエリのサマリーを確認する(実行例) # $ sudo mysqldumpslow -s t /var/log/mysql/slow.log # Reading mysql slow query log from /var/log/mysql/slow.log # Count: 5 Time=3.20s (16s) Lock=0.00s (0s) Rows=1000.0 (5000) # SELECT * FROM orders WHERE status = 'pending' ORDER BY created_at DESC
3. query_cache_sizeの注意点(MySQL 8.0では廃止)
query_cache_sizeはSELECT結果をキャッシュする機能ですが、MySQL 8.0でこの機能は完全に廃止されました。MySQL 5.7では非推奨(deprecated)となっており、8.0のmy.cnfに記述するとサーバーが起動しなくなります。・MySQL 8.0以降: query_cache_sizeは設定禁止(記述するとMySQLが起動しない)
・MySQL 5.7: 明示的に0または無効化(query_cache_type=0)を推奨
・MariaDB 10.x: 引き続き利用可能。読み取り中心のワークロードで有効な場合がある
# MySQL 5.7 の場合: クエリキャッシュを明示的に無効化する [mysqld] query_cache_type = 0 query_cache_size = 0 # MySQL 8.0 以降の場合: 上記2行を完全に削除すること # ファイルに記述するだけでエラーになり起動しない # MariaDB の場合: 利用する場合の設定例 # [mysqld] # query_cache_type = 1 # query_cache_size = 64M # query_cache_limit = 1M # バージョン確認 # $ mysql --version # mysql Ver 8.0.36 for Linux on x86_64 (MySQL Community Server - GPL)
チューニング後の検証:SHOW STATUS / SHOW VARIABLES の読み方
my.cnfを変更した後は、実際に効果が出ているかを数値で確認することが重要です。「設定した=完了」ではなく「効果を確認した=完了」です。1. バッファプールのヒット率を確認する
バッファプールのヒット率(キャッシュヒット率)が99%以上であれば、innodb_buffer_pool_sizeは適切と判断できます。ヒット率が低い場合はバッファプールのサイズが不足しています。# バッファプールのヒット率を確認する mysql> SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%'; +---------------------------------------+--------+ | Variable_name | Value | +---------------------------------------+--------+ | Innodb_buffer_pool_read_ahead | 192 | | Innodb_buffer_pool_read_ahead_evicted | 0 | | Innodb_buffer_pool_read_ahead_rnd | 0 | | Innodb_buffer_pool_read_requests | 584320 | | Innodb_buffer_pool_reads | 1248 | +---------------------------------------+--------+ # ヒット率の計算式 # ヒット率(%) = (1 - reads / read_requests) x 100 # 上の例: (1 - 1248 / 584320) x 100 = 99.79% → 問題なし # ヒット率が95%を下回る場合 → innodb_buffer_pool_size を増やすことを検討する # ヒット率が90%を下回る場合 → 早急にinnodb_buffer_pool_sizeを見直す必要がある
2. 接続関連のステータスを確認する
接続数に関するステータスを確認することで、max_connectionsの過不足を判断できます。Connection_errors_max_connectionsがゼロでない場合は、max_connectionsの上限に達していることを意味します。# 接続関連の主要ステータスを確認する mysql> SHOW GLOBAL STATUS WHERE Variable_name IN ( 'Threads_connected', 'Threads_running', 'Max_used_connections', 'Connection_errors_max_connections', 'Aborted_connects' ); +-----------------------------------+-------+ | Variable_name | Value | +-----------------------------------+-------+ | Aborted_connects | 3 | | Connection_errors_max_connections | 0 | | Max_used_connections | 47 | | Threads_connected | 12 | | Threads_running | 2 | +-----------------------------------+-------+ # Connection_errors_max_connections が増加している場合 # → max_connections の上限に達している → 値を増やす必要がある # Aborted_connects が多い場合 # → 認証失敗・タイムアウト等が発生している → ログを調査する # Threads_running が Threads_connected に近い場合 # → 多数のクエリが同時実行中 → ボトルネックの調査が必要
3. 設定の全量を一括確認する方法
設定変更の効果を確認する際は、変更した変数を直接確認するのが最も確実です。# 主要なパフォーマンス関連変数を一括確認する mysql> SHOW GLOBAL VARIABLES WHERE Variable_name IN ( 'innodb_buffer_pool_size', 'innodb_buffer_pool_instances', 'max_connections', 'innodb_log_file_size', 'slow_query_log', 'long_query_time' ); +------------------------------+------------+ | Variable_name | Value | +------------------------------+------------+ | innodb_buffer_pool_instances | 4 | | innodb_buffer_pool_size | 4294967296 | | innodb_log_file_size | 268435456 | | long_query_time | 1.000000 | | max_connections | 200 | | slow_query_log | ON | +------------------------------+------------+ # innodb_buffer_pool_size = 4294967296 バイト = 4GB → 設定通り
よくある設定ミスとトラブル対応
my.cnfのチューニングでよく見かけるミスと、その対処法をまとめます。1. MySQLが起動しない場合:エラーログを最初に確認する
設定変更後にMySQLが起動しない場合は、必ずエラーログを確認します。設定値の書き方ミス・廃止された設定の残留・メモリ不足が原因の大半を占めます。# エラーログを確認する(直近の50行) $ sudo tail -50 /var/log/mysqld.log $ sudo tail -50 /var/log/mysql/error.log # Ubuntu/Debian の場合 # 実際のエラー例(MySQL 8.0でquery_cache_sizeを記述した場合) # [ERROR] [MY-011011] [Server] Failed to find valid data directory. # [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. # または # [ERROR] unknown variable 'query_cache_size=0' # 起動前に設定ファイルのシンタックスチェックを行う $ sudo mysqld --validate-config # MariaDB の場合 $ sudo mariadbd --validate-config
2. innodb_buffer_pool_sizeを大きくしすぎた場合
innodb_buffer_pool_sizeをRAMの90%以上に設定すると、OSやその他のプロセスが使えるメモリが不足し、スワップが発生してかえって遅くなることがあります。スワップが発生しているかどうかを確認しましょう。# スワップの使用状況を確認する $ free -h total used free shared buff/cache available Mem: 7.6Gi 6.9Gi 145Mi 25Mi 583Mi 382Mi Swap: 2.0Gi 892Mi 1.1Gi # Swap の used が増加している場合はメモリが不足している # innodb_buffer_pool_size を10~20%削減することを検討する # メモリをプロセス別に確認する $ ps aux --sort=-%mem | head -10
3. 動的変更:再起動なしに設定を反映させる方法
MySQL 5.7.5以降では、innodb_buffer_pool_sizeを再起動なしに動的変更できます。本番環境でメンテナンスウィンドウが取れない場合に有効です。ただし、この変更はmy.cnfには反映されないため、設定ファイルへの追記も忘れずに行ってください。# 動的にinnodb_buffer_pool_sizeを4GBに変更する(MySQL 5.7.5以降) mysql> SET GLOBAL innodb_buffer_pool_size = 4294967296; # 4294967296 = 4 x 1024 x 1024 x 1024 = 4GB # 変更中の進捗を確認する(大きい値への変更は時間がかかる場合がある) mysql> SHOW STATUS LIKE 'Innodb_buffer_pool_resize_status'; +----------------------------------+----------------------------------------------------+ | Variable_name | Value | +----------------------------------+----------------------------------------------------+ | Innodb_buffer_pool_resize_status | Completed resizing buffer pool at 240815 9:30:15. | +----------------------------------+----------------------------------------------------+ # 変更後の確認 mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size'; +-------------------------+------------+ | Variable_name | Value | +-------------------------+------------+ | innodb_buffer_pool_size | 4294967296 | +-------------------------+------------+
まとめと次のステップ
my.cnfのチューニングで押さえるべきポイントを整理します。| パラメータ | 推奨設定値の目安 | 注意事項 |
|---|---|---|
| innodb_buffer_pool_size | 空きRAMの70~80%(専用)/ 50~60%(同居) | 最もパフォーマンスに影響する。最優先で設定する |
| innodb_buffer_pool_instances | バッファプール(GB)と同数(最大16) | 1GB超の場合のみ設定。並列アクセスのロック競合を軽減 |
| max_connections | Max_used_connectionsの1.5~2倍 | per-threadバッファのメモリ試算必須。闇雲に増やさない |
| innodb_log_file_size | buffer_pool_sizeの25%程度 | MySQL 8.0.30以降はinnodb_redo_log_capacityに変更 |
| slow_query_log | ON(long_query_time=1) | 本番環境では必須。mysqldumpslow でサマリー確認 |
| query_cache_size | MySQL 8.0: 記述禁止 / MariaDB: 任意 | MySQL 8.0では廃止済み。記述するだけで起動不能になる |
チューニングは「設定して終わり」ではありません。設定変更後は必ず
SHOW GLOBAL STATUSでバッファプールのヒット率(99%以上が目標)と最大同時接続数を確認してください。スワップの発生有無もfree -hコマンドで定期的に確認する習慣をつけましょう。MySQLの設定パラメータはバージョンごとに変更・廃止されます。特にMySQL 5.7から8.0への移行時はquery_cache_size等の廃止変数の残留が起動障害の典型的な原因となります。バージョンアップ前には必ず公式リリースノートの「Removed Features」を確認してください。
次のステップとして、slow_query_logに記録されたクエリに対してEXPLAIN文でインデックス不足を特定し、インデックスの最適化に取り組むことをお勧めします。my.cnfのチューニングとインデックス設計の両輪で、MySQLのパフォーマンスを最大限引き出せます。
Linux無料マニュアルを受け取る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:PostgreSQLをPGDGリポジトリからLinuxへ導入する手順|initdbとサービス起動・初期ロール設定まで
- この記事の属するカテゴリ:データーベース管理へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます