MySQLのmy.cnfでパフォーマンスチューニングをする方法|InnoDBバッファプールと主要変数の設定

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Linuxtips > データーベース管理 > MySQLのmy.cnfでパフォーマンスチューニングをする方法|InnoDBバッファプールと主要変数の設定
「MySQLが重くなってきた」「16GBのメモリを積んでいるのに、なぜか全部使われていない」

Linuxサーバー上でMySQLをセルフホスト運用していると、インストール直後のデフォルト設定のまま運用し続けることで、メモリの大半がDBキャッシュに活かされていない状態になります。設定ファイルを一切変更していない場合、InnoDBのバッファプールはデフォルトで128MBしか割り当てられていません。

この記事では、RHEL 9系/Rocky Linux 9およびUbuntu 24.04 LTSを想定環境として、my.cnfの主要パラメータの意味と設定手順を解説します。InnoDBバッファプールサイズの調整を中心に、接続数・タイムアウト・バイナリログ保持期間の設定まで、順を追って説明します。MariaDB 10.x系でも設定項目はほぼ共通です。

この記事のポイント

・InnoDBバッファプールサイズはRAMの50~70%を目安に設定する
・SHOW VARIABLES / SHOW STATUSで現状を数値で把握してから変更する
・max_connections超過時は「Too many connections」エラーが発生する
・変更前にmysqld --validate-configで構文を検証してから再起動する


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

デフォルトのmy.cnfで何が足りないのか

MySQLをパッケージインストールした直後のmy.cnfは、汎用的な最低設定が入っているだけです。特に問題になりやすいのがinnodb_buffer_pool_sizeの小ささです。このパラメータはInnoDBがデータとインデックスをメモリにキャッシュするための領域を指定するもので、デフォルト値は128MBに設定されています。

サーバーに16GBのRAMが搭載されていても、デフォルトのままでは128MBしかDBキャッシュに使われません。残りのメモリはDBには利用されず、テーブルデータをディスクから何度も読み込み続ける状態になります。これがI/O増加とクエリ遅延の主因です。

デフォルト設定のままでよく起きる症状は以下のとおりです。
・クエリの応答時間が負荷と共に悪化する
・iostatでディスクI/O待ちが常態化する
・接続数が多い時間帯に「Too many connections」エラーが出始める
・スロークエリログに同じクエリが繰り返し記録される

これらを解消するには、サーバーのRAM搭載量や用途に合わせてmy.cnfを明示的に調整する必要があります。

チューニング前に現状を数値で把握する

my.cnfを変更する前に、SHOW VARIABLESとSHOW STATUSで現在の設定値と稼働状況を確認します。数値を把握せずに設定を変えると、症状を改善するどころか悪化させる場合もあります。まず現状を記録してから作業に入ることが重要です。

1. 設定値をSHOW VARIABLESで確認する

# MySQL/MariaDB にログイン mysql -u root -p # バッファプール・接続数などの設定値を確認 SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'innodb_buffer_pool_instances'; SHOW VARIABLES LIKE 'max_connections'; SHOW VARIABLES LIKE 'wait_timeout'; SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';

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

+--------------------------+-----------+ | Variable_name | Value | +--------------------------+-----------+ | innodb_buffer_pool_size | 134217728 | +--------------------------+-----------+ +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+

134217728は128MBです。8GBや16GB以上のRAMを積んだサーバーには明らかに小さすぎる値です。この数値を確認してから、次の手順でキャッシュヒット率を調べます。

2. バッファプールのヒット率をSHOW STATUSで確認する

# バッファプールのキャッシュヒット率を確認 SHOW STATUS LIKE 'Innodb_buffer_pool_read%'; # 接続数の現状を確認 SHOW STATUS LIKE 'Max_used_connections'; SHOW STATUS LIKE 'Threads_connected';

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

+----------------------------------+-------+ | Variable_name | Value | +----------------------------------+-------+ | Innodb_buffer_pool_reads | 48291 | | Innodb_buffer_pool_read_requests | 51284 | +----------------------------------+-------+

Innodb_buffer_pool_readsはディスクから実際に読み込んだ回数、Innodb_buffer_pool_read_requestsはキャッシュへのアクセス要求数です。ヒット率の目安は次の計算式で確認できます。

キャッシュヒット率(%)=(1 − Innodb_buffer_pool_reads ÷ Innodb_buffer_pool_read_requests)× 100

上の例だと 1 − 48291 ÷ 51284 ≒ 5.8%(ヒット率)です。本来は99%以上が健全な状態で、5.8%はほぼキャッシュが機能していない状態を意味します。バッファプール拡張の優先度が高いことがわかります。

InnoDBバッファプールサイズを設定する

DBパフォーマンス改善の中で最も効果が高い変更がinnodb_buffer_pool_sizeの拡張です。一般的な目安はサーバーRAMの50~70%です。DBサーバー専用機なら70%まで割り当てられますが、WebサーバーやアプリケーションサーバーとDBが同居している場合は50%程度に留め、OS側のメモリを確保します。

計算の参考(RAMが16GBの場合)
・DBサーバー専用: 16GB × 70% ≒ 11GB → innodb_buffer_pool_size = 11G
・WebとDB同居: 16GB × 50% ≒ 8GB → innodb_buffer_pool_size = 8G

1. my.cnfファイルの場所を確認する

設定ファイルの場所はディストリビューションによって異なります。
・RHEL 9 / Rocky Linux 9: /etc/my.cnf
・Ubuntu 24.04 LTS(MySQL 8.x): /etc/mysql/mysql.conf.d/mysqld.cnf
・MariaDB on Ubuntu: /etc/mysql/mariadb.conf.d/50-server.cnf

# どのファイルが実際に読み込まれているかを確認 mysql --help --verbose 2>/dev/null | grep -A1 'Default options'

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

Default options are read from the following files in the given order: /etc/my.cnf /etc/mysql/conf.d/*.cnf ~/.my.cnf

複数のファイルが読み込まれる場合、後から読まれるファイルの設定が優先されます。設定値が反映されない時は、読み込み順を確認します。

2. my.cnfにパラメータを追記する

# /etc/my.cnf(RHEL 9 / Rocky Linux 9の場合) [mysqld] # InnoDBバッファプールサイズ(RAMの50~70%を目安に設定) innodb_buffer_pool_size = 8G # バッファプールインスタンス数(合計サイズが1GB以上なら8が推奨) innodb_buffer_pool_instances = 8

innodb_buffer_pool_instancesはバッファプールを内部で分割する数です。合計サイズが1GB以上の場合は8に設定すると、内部ロックの競合が減り、並列アクセス時の応答が改善します。MySQL 8.0ではデフォルトが自動設定になっていますが、明示的に8と書いておくほうが意図が伝わりやすく管理しやすいです。

接続数とタイムアウトを調整する

Webアプリから多数の同時接続が来る構成では、max_connectionsのデフォルト値(151)では「Too many connections」エラーが発生することがあります。ただし、単純に増やすだけでは各接続に必要なスレッドメモリも比例して増加するため、他のパラメータとのバランスが重要です。

変更前にMax_used_connections(稼働開始以降の最大同時接続数)を確認し、実際に上限に近づいているかを検証してから設定値を決めます。

1. 接続数の上限を見直す

# これまでの最大接続数を確認 SHOW STATUS LIKE 'Max_used_connections'; # 現在の接続数を確認 SHOW STATUS LIKE 'Threads_connected';

Max_used_connectionsが151に近い値を示している場合は、max_connectionsを引き上げる必要があります。設定の目安として、最大同時接続数の1.5倍程度を上限に設定するのが一般的です。

2. タイムアウト値を設定する

# /etc/my.cnf [mysqld] # 最大同時接続数(Max_used_connectionsを基に設定) max_connections = 300 # スリープ接続のタイムアウト(秒) # デフォルトは28800秒(8時間) wait_timeout = 600 interactive_timeout = 600

wait_timeoutはスリープ状態(クエリを実行していない状態)の接続が切断されるまでの時間です。デフォルトの28800秒(8時間)は長すぎるため、WebアプリがDBコネクションプールを使っている構成では、ゾンビ接続がmax_connectionsの枠を長時間占有する原因になります。600秒(10分)程度に短縮することで、不要なコネクションが早めに解放されます。

MySQLのパラメータ設定を体系的に学びたい場合は、Linux実践セミナーでも実サーバーを使った設定確認の手順を扱っています。

バイナリログの保持期間を管理する

バイナリログ(binlog)は更新系クエリの記録をファイルに蓄積します。保持期間を設定しないと、ディスクが枯渇するまでログが積み重なり続けます。ポイントインタイムリカバリやレプリケーションを利用している場合は削除できませんが、不要なログが7日以上溜まっている場合は保持期間を設定します。

MySQL 8.0以降はbinlog_expire_logs_seconds(秒単位)が推奨パラメータです。MySQL 5.7以前やMariaDB 10.x系ではexpire_logs_days(日単位)を使います。

# /etc/my.cnf [mysqld] # MySQL 8.0以降: バイナリログを7日間保持(604800秒) binlog_expire_logs_seconds = 604800 # MariaDB / MySQL 5.7以前の場合(日単位、コメントアウトして使用) # expire_logs_days = 7

現在のバイナリログの蓄積状況は次のコマンドで確認できます。

# バイナリログのファイル一覧を確認 SHOW BINARY LOGS;

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

+------------------+-----------+-----------+ | Log_name | File_size | Encrypted | +------------------+-----------+-----------+ | mysql-bin.000041 | 2097152 | No | | mysql-bin.000042 | 1048576 | No | | mysql-bin.000043 | 524288 | No | +------------------+-----------+-----------+

バイナリログをまったく使わない構成の場合はskip-log-binをmy.cnfに追記して無効化できます。ただし、無効化するとポイントインタイムリカバリができなくなるため、バックアップ戦略を見直した上で判断してください。

設定変更後の確認と再起動手順

my.cnfを変更したら、MySQLを再起動する前に設定ファイルの構文チェックを必ず行います。パラメータ名のタイプミスや不正な値が含まれていると、再起動後にMySQLが起動しなくなります。

1. 設定ファイルの構文を検証する

# MySQL 8.0以降: 設定ファイルの構文を検証 mysqld --validate-config # エラーがなければ出力なしで終了する echo "終了コード: $?"

出力例(不正なパラメータがある場合、環境により異なります)

2024-01-15T10:30:00.000000Z 0 [ERROR] [MY-000067] [Server] unknown variable 'innoodb_buffer_pool_size=8G'.

エラーが出た場合は、表示されたパラメータ名を確認してmy.cnfを修正します。上の例では「innoodb」というタイプミスが原因です。

2. サービスを再起動して設定を反映する

# RHEL 9 / Rocky Linux 9 の場合 sudo systemctl restart mysqld # Ubuntu 24.04 LTS(MySQL 8.x)の場合 sudo systemctl restart mysql # MariaDB の場合(RHEL系/Ubuntu共通) sudo systemctl restart mariadb

3. 設定値が反映されたか確認する

# 再起動後に設定値が反映されているか確認 mysql -u root -p -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';" mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';"

4. エラーログで起動成否を確認する

# MySQLエラーログの末尾を確認 sudo tail -30 /var/log/mysqld.log # RHEL 9 / Rocky Linux sudo tail -30 /var/log/mysql/error.log # Ubuntu 24.04 LTS

[ERROR]が含まれる行があれば、パラメータ名とメッセージを手がかりにmy.cnfを修正して再起動します。ready for connectionsのメッセージが出ていれば正常起動しています。

よくある設定ミスとエラーの対処法

「InnoDB: Requested too large」で起動しない

innodb_buffer_pool_sizeをサーバーの物理RAMを超えて設定した場合、MySQLが起動できずこのエラーが発生します。エラーログでRequested too largeのメッセージを確認し、サイズを物理RAM内に収まる値に修正してから再起動します。

確認コマンド(サーバーの総メモリ量を確認する)

free -h

「Too many connections」が解消されない

max_connectionsを引き上げてもエラーが続く場合、アプリ側の接続プールが接続を正常にクローズしていない可能性があります。SHOW PROCESSLISTでスリープ状態の接続数を確認します。

# スリープ状態の接続一覧と滞留時間を確認 SELECT user, host, db, command, time FROM information_schema.processlist WHERE command = 'Sleep' ORDER BY time DESC LIMIT 20;

TIMEの値が大きい(数百秒以上の)スリープ接続が多い場合、wait_timeoutを短縮することで自動切断されるようになります。

「Variable is a read only variable」(動的変更を試みた場合)

SET GLOBAL innodb_buffer_pool_size = ...で動的に変更を試みた際にこのエラーが出ることがあります。innodb_buffer_pool_sizeはMySQL 8.0.3以降で動的変更に対応していますが、サイズを大きく変更する場合や一部のMySQL/MariaDBバージョンでは変更が受け付けられません。動的変更が使えない場合は、my.cnfを変更してサービスを再起動する方法で設定します。

本記事のまとめ

MySQLのmy.cnfで効果が高い主要パラメータをまとめます。
パラメータ デフォルト値 推奨設定の目安
innodb_buffer_pool_size 128MB RAMの50~70%(DBサーバー専用なら70%)
innodb_buffer_pool_instances 自動 合計1GB以上なら8
max_connections 151 Max_used_connectionsの1.5倍程度
wait_timeout 28800秒(8時間) 600秒(Webアプリ接続プール運用時)
interactive_timeout 28800秒(8時間) wait_timeoutと同じ値に揃える
binlog_expire_logs_seconds 2592000秒(30日) 604800秒(7日)など運用に応じて
変更の手順は「①SHOW VARIABLES/STATUSで現状把握 → ②my.cnfを編集 → ③mysqld --validate-configで検証 → ④再起動 → ⑤エラーログ確認」の流れで進めます。設定を変えるたびにこの流れを踏むことで、起動不能のリスクを最小化できます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、MySQL/MariaDBの実践的な設定・チューニングからトラブル対応まで体系的に学べる2日間のハンズオンセミナーを開催しています。
>> Linuxサーバー構築セミナーの詳細と日程はこちら

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

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

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

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

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

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

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

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

運営

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

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