ある時期を境に、本ブログをホストしているWordPressサーバーのMySQLが頻繁に落ちるようになった。
それまではせいぜい年に数回の頻度だったのが、2025年5月頃から月に数回のペース、直近では毎週のようにMySQLが落ちるようになった。
一応、MySQLのプロセスを監視・再起動するスプクリプトをcronで回しているのだが、さすがに放置できなくなり、サーバーのチューニングを行った。
結論から言うと、スワップ領域を作成して有効化することで収束したのだが、そこに至るまでに色々なことをやったので、メモ。
ただし、これまでスワップ領域なしで安定稼働していたMySQLが、何故この1年で急に落ちるようになったのかは究明できていない。
環境
- ホスティングプロバイダー: DigitalOcean
- OS: Ubuntu
- メモリ: 1GB
- ディスク: 25GB
通常、MySQLの設定ファイルはLinuxならmy.cnf、Windowsならばmy.iniだが、自分の環境だと/etc/mysql/mysql.conf.d/mysqld.cnfに設定を反映しなければならなかった。
OSおよびアプリケーションのアップデート
ちょうどいい機会なのでUbuntu、PHP、Apache、MySQLをまとめてアップデートした。しかしアップデート後も問題は解決しなかった。
MySQLのエラーログのログレベルを変更
以下は直近でMySQLが落ちた時のerror.logの内容である。
2026-02-17T10:20:28.241371Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.45-0ubuntu0.22.04.1) starting as process 1987184
2026-02-17T10:20:28.274114Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2026-02-17T10:20:29.535270Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2026-02-17T10:20:30.061710Z 0 [System] [MY-010229] [Server] Starting XA crash recovery...
2026-02-17T10:20:30.098036Z 0 [System] [MY-010232] [Server] XA crash recovery finished.
2026-02-17T10:20:30.255808Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2026-02-17T10:20:30.255959Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2026-02-17T10:20:30.370510Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '127.0.0.1' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2026-02-17T10:20:30.370954Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.45-0ubuntu0.22.04.1' socket: '/var/run/mysqld/mysqld.sock' port: 3306 (Ubuntu).
2026-02-17T10:20:30.584361Z 8 [Warning] [MY-013360] [Server] Plugin mysql_native_password reported: ''mysql_native_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'
MySQLが再起動したことしか記録されていない。昔ログを見たときはもっと色々記録されていたのに。。。
MySQLに接続し、show variablesでlog_error_verbosityの値を確認したところ2になっていた。
| log_error_verbosity | 2
/etc/mysql/mysql.conf.d/mysqld.cnfに以下を記述して、ログレベルを最大にした。
log_error_verbosity=3
MySQLを再起動し設定が反映されたことを確認。
mysql> show variables like '%log_error_verbosity%';
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| log_error_verbosity | 3 |
+---------------------+-------+
1 row in set (0.00 sec)
スロークエリの改善
こちらの記事を読んでいてスロークエリなるものの存在を知った。/etc/mysql/mysql.conf.d/mysqld.cnfに以下を記述してスロークエリのログを有効化。
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 3
後日、mysql-slow.logを確認したところ、ちょうどMySQLが落ちていた時間帯に以下のスロークエリが発生していた。
SELECT option_name, option_value FROM wp_options WHERE autoload IN ( 'yes', 'on', 'auto-on', 'auto' );
WordPressのデータベースに接続し、autoloadのサイズを確認したところ、_transient_dirsize_cacheのautoloadが最も大きかった。(参考)
mysql> connect wordpress;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Connection id: 376
Current database: wordpress
mysql> SELECT option_name, LENGTH(option_value) AS size
-> FROM wp_options
-> WHERE autoload = 'yes'
-> ORDER BY size DESC
-> LIMIT 20;
+--------------------------------------------+-------+
| option_name | size |
+--------------------------------------------+-------+
| _transient_dirsize_cache | 34982 |
| -- snipped --- |
Geminiによると_transient_dirsize_cacheのautoloadが大きすぎると、MySQLのパフォーマンス低下につながるらしい。_transient_dirsize_cacheのautoloadオプションを無効化した。
UPDATE wp_options
SET autoload = 'no'
WHERE option_name = '_transient_dirsize_cache';
しかし、これでも問題は解決しなかった。
MySQLTunerで診断
MySQLTunerで診断してみた。以下は診断結果。
-------- Recommendations ---------------------------------------------------------------------------
General recommendations:
MySQL was started within the last 24 hours: recommendations may be inaccurate
Configure your accounts with ip or subnets only, then update your configuration with skip-name-resolve=ON
Variables to adjust:
skip-name-resolve=ON
innodb_buffer_pool_size (>= 214.8M) if possible.
innodb_log_buffer_size (> 16M)
skip_name_resolveというのはホスト名の名前解決を行うか否かを指定する変数らしい。この変数がOFFになっていると、クライアントから接続があった場合ホスト名の名前解決を行い、ONの場合は名前解決せずにIPアドレスと直で通信する模様。
ONにして問題なさそうなので、/etc/mysql/mysql.conf.d/mysqld.cnfに以下を記述。
skip_name_resolve=ON
innodb_buffer_pool_sizeにはInnoDBがテーブルやインデックスのデータをキャッシュする領域のサイズを指定し、innodb_log_buffer_sizeはInnoDBがログファイルを書く際に使用するバッファのサイズを指定するらしい。
で、どちらの変数にもMySQLTunerが推奨した値を設定したのだが、途端にサイトが遅くなってしまったので慌てて元の値に戻した。多分、適切な値を指定すればパフォーマンスの向上につながるのだろうが、適切な値がわからないため、この2つの変数はいじらないでおいた。
ちなみにデフォルトの値は以下の通り。
mysql> show variables like '%innodb_buffer_pool_size%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
1 row in set (0.02 sec)
mysql> show variables like '%innodb_log_buffer_size%';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set (0.00 sec)
スワップ領域を作成して有効化
引き続きトラブルシューティングのためにググっていたところ、スワップ領域を作成して有効化したことで同様の事象を解決したという記事をチラホラ見かけた。
freeコマンドでメモリの使用状況を確認したところ、Swapの欄が0になっていた。
その時のfreeコマンドのアウトプットは取っていなかったのだが、同じ時に叩いたtopコマンドのアウトプットは取ってあったので、貼っておく。
top - 13:34:04 up 119 days, 23:13, 1 user, load average: 0.03, 0.05, 0.00
Tasks: 107 total, 1 running, 106 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.6 us, 0.6 sy, 0.0 ni, 89.7 id, 1.9 wa, 0.0 hi, 0.0 si, 5.1 st
MiB Mem : 957.3 total, 73.3 free, 732.3 used, 151.7 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 56.0 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1987184 mysql 20 0 1376412 461088 8024 S 2.6 47.0 3:28.04 mysqld
1988349 www-data 20 0 443416 55164 38692 S 2.0 5.6 0:05.24 apache2
83 root 0 -20 0 0 0 I 0.3 0.0 19:52.24 kworker/0:1H-kblockd
271 root 20 0 0 0 0 S 0.3 0.0 8:50.78 jbd2/vda1-8
1989334 root 20 0 12928 4792 3840 R 0.3 0.5 0:00.03 top
topコマンドからもスワップ領域が0であることが伺える。
先述した記事を参考にスワップ領域を作成・有効化することに。
以下のddコマンドでスワップ領域用のファイル(/swapfile)を作成。
dd if=/dev/zero of=/swapfile bs=1M count=1024
mkswapでスワップ領域を作成。
mkswap /swapfile
この際、ファイルのパーミッションをもっとしっかり設定しろと注意された。
mkswap: /swapfile: insecure permissions 0644, fix with: chmod 0600 /swapfile
アドバイスに従い、パーミッションを厳格化。
chmod 0600 /swapfile
swaponでスワップ領域を有効化。
swapon /swapfile
スワップ領域が使用されていることを確認。
# swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 1024M 121.8M -2
最後に/etc/fstabに以下を追記してシステム起動時にスワップ領域がマウントされるように設定。
/swapfile swap swap defaults 0 0
経過
スワップ領域を作成してから1週間ほどが経過したが、MySQLが落ちることはなくなった。
ただ、冒頭でも述べたように、これまでスワップ領域なしで安定稼働していたMySQLが、何故この1年で急に落ちるようになったのかは究明できていない。