MySQLが頻繁に落ちるので、対策としてやったことのメモ

ある時期を境に、本ブログをホストしている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 variableslog_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_cacheautoloadが最も大きかった。(参考)

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_cacheautoloadが大きすぎると、MySQLのパフォーマンス低下につながるらしい。
_transient_dirsize_cacheautoloadオプションを無効化した。

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年で急に落ちるようになったのかは究明できていない。

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.