MySQL InnoDBトラブル
2022.09.12
YouTube でも紹介しています。画像をクリックすると再生できます。
突然、自宅WEBサーバーのブログが表示されなくなってしまいました。
容易にDBMSの障害であることはわかるので、待機サーバへの切り替えは行わず、対処することにしました。
ちなみに、毎日1回自動的にデータベースのバックアップをとっているので、最悪1日前の状態には復帰できます。
■原因解明
MySQLのプロセスが停止していたので、一応再起動を掛けてみました。
$ sudo service mysql start
Job for mysql.service failed because the control process exited with error code.
See "systemctl status mysql.service" and "journalctl -xe" for details.
エラーとなり、起動ません。
journalctl -xe
journalctlコマンドは、systemd-journaldが収集したログを表示するためのコマンドです。
-xe オプションは最近のログの詳細情報を表示します。
このログをみても、いまいち原因がわかりませんでしたが、ついでにジャーナルファイルを整理しておきました。
ジャーナルの使用容量を確認します
$ journalctl --disk-usage
Archived and active journals take up 1.7G in the file system.
3日より前のエントリーを削除します
$ sudo journalctl --vacuum-time=3d
ステータスメッセージとジャーナルログからは決定的な原因がわからなかったので、MySQLのエラーログをみることにしました。
$ tail -n 20 /var/log/mysql/error.log
~
2022-09-11T10:53:51.677880Z 0 [ERROR] InnoDB: mmap(137428992 bytes) failed; errno 12
2022-09-11T10:53:51.677918Z 0 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
2022-09-11T10:53:51.677944Z 0 [ERROR] InnoDB: Plugin initialization aborted with error Generic error
~
InnoDBでエラーになっていて、メモリーが不足していることがわかります。
■設定変更
MySQLのデータベース・エンジンには、MyISAM と InnoDB があるのですが、
現状、用途的にMyISAMで十分足りていて、InnoDBは使っていません。
そこで、InnoDBが起動しないように設定を変更してみました。
また、明示的にデフォルトのストレージエンジンに、MyISAMを指定しています。
$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
skip-innodb
default-storage-engine=MyISAM
$ sudo service mysql start
しかし、エラーとなり起動しません。
再度、エラーログをみてみると、
$ tail -n 20 /var/log/mysql/error.log
2022-09-11T10:56:43.236292Z 0 [Warning] The use of InnoDB is mandatory since MySQL 5.7. The former options like '--innodb=0/1/OFF/ON' or '--skip-innodb' are ignored.
MySQL 5.7 以降、InnoDB の使用は必須になっていました。
skip-innodb オプションは削除しました。
■スワップ領域の確保
仕方がないので、スワップ領域を作ることにしました。
まずはスワップ領域の確認です。
$ sudo swapon --show
なにも表示されなかったので、スワップ領域を確保していないことがわかります。
いままで、スワップ領域なしに普通にさくさくと動いていたので、スワップ領域を設定していませんでした。
ディスクの空き領域を確認します。
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 440M 0 440M 0% /dev
tmpfs 92M 4.4M 87M 5% /run
/dev/sda1 234G 8.7G 214G 4% /
tmpfs 457M 0 457M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 457M 0 457M 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 96M 157M 38% /boot/firmware
tmpfs 92M 0 92M 0% /run/user/1000
Mounted onの欄に / が表示されているデバイスがディスクです。
ストレージには、256GBのSSDを使用していますが、空き領域はたっぷりあります。
1GBのスワップ領域を作ります。
$ sudo fallocate -l 1G /swapfile
$ ls -lh /swapfile
-rw-r--r-- 1 root root 1.0G 9月 11 11:02 /swapfile
root権限のみにアクセス許可を与えます。
$ sudo chmod 600 /swapfile
$ ls -lh /swapfile
-rw------- 1 root root 1.0G 9月 11 11:02 /swapfile
ファイルをスワップ領域としてマークします。
$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=22d34fcc-2b561-1234-bca4-c45fa32a2112
スワップファイルを有効にします。
$ sudo swapon /swapfile
スワップが使用可能であることを確認します。
$ sudo swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 1024M 0B -2
メモリの利用状況を確認します。
$ free -h
total used free shared buff/cache available
Mem: 912M 651M 98M 8.0M 162M 238M
Swap: 1.0G 0B 1.0G
MySQLを起動します。
$ sudo service mysql start
無事に、MySQLが起動するようになりました。
MySQL起動後のメモリー使用状況をみてみます。
$ free
total used free shared buff/cache available
Mem: 933944 702316 39620 3864 192008 212568
Swap: 1048572 163840 884732
スワップ領域が使用されていることがわかります。
システムを再起動すると、サーバーはスワップ設定を自動的に保持しません。
そこで、スワップファイルの永続化を行います。
$ sudo cp -p /etc/fstab /etc/fstab.bak
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
■待機サーバーへの反映
待機サーバーにも同様の設定を行います。
■システム再起動
スワップ領域を設定して、MySQLを再起動して、1週間後、SWAP領域が一杯になり、MySQLサービスがダウンしてしまいました。
システム再起動はリスクが高いので、サーバー・リプレイス以来、1年半、システムの再起動は行っていなかったのですが、
システムをリブートすることにしました。
一応事前に、InnoDB のバッファプール・サイズを設定しておきました。
バッファプールは、アクセスされたテーブルデータやインデックスデータをキャッシュし、リクエストを高速に処理するための重要な機構です。
$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
innodb_buffer_pool_size = 512M
$ sudo reboot
システム再起動後のメモリー使用状況を確認してみます。
$ free
total used free shared buff/cache available
Mem: 933944 401852 173028 7476 359064 509436
Swap: 1048572 0 1048572
スワップ領域の使用がゼロになりました。
■その他の処理
エラーログをみてみると、警告もでていたので対処しておきます。
[Warning]TIMESTAMP with implicit DEFAULT value is deprecated.
Please use --explicit_defaults_for_timestamp server option
(see documentation for more details).
$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
explicit_defaults_for_timestamp = 1
これは自己責任で行ってほしいのですが、ログファイルが膨れていたので削除しました。
$ sudo ls -al /var/lib/mysql
....
-rw-r----- 1 mysql mysql 50331648 9月 9 21:57 ib_logfile0
-rw-r----- 1 mysql mysql 50331648 5月 21 2019 ib_logfile1
-rw-r----- 1 mysql mysql 12582912 9月 9 21:57 ibdata1
-rw-r----- 1 mysql mysql 12582912 9月 10 03:36 ibtmp1
....
$ sudo mkdir /var/lib/mysql_backup
$ cd /var/lib/mysql_backup
$ sudo cp -p ../mysql/ib_logfile0 ./
$ sudo cp -p ../mysql/ib_logfile1 ./
$ sudo rm ../mysql/ib_logfile0
$ sudo rm ../mysql/ib_logfile1
■参考文献
・Ubuntu 20.04にスワップ領域を追加する方法
|