fluid_27’s blog

勉強した内容をアウトプットするためのブログ

MySQLが落ちるの時の対処

AWSでデプロイしたアプリがMySQLが落ちた事が原因でエラーになっていた。

 

 

エラーログ

MySQLのログを見てみると

2021-06-27T22:58:07.430585Z 0 [ERROR] [MY-012681] [InnoDB] mmap(137035776 bytes) failed; errno 12

2021-06-27T22:58:07.430701Z 1 [ERROR] [MY-012956] [InnoDB] Cannot allocate memory for the buffer pool

2021-06-27T22:58:07.430767Z 1 [ERROR] [MY-012930] [InnoDB] Plugin initialization aborted with error Generic error.

2021-06-27T22:58:07.430856Z 1 [ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine

2021-06-27T22:58:07.431029Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.

2021-06-27T22:58:07.431169Z 0 [ERROR] [MY-010119] [Server] Aborting

2021-06-27T22:58:07.436718Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.25)  MySQL Community Server - GPL.

 というログが。

 2段目に Cannot allocate memory for the buffer poolとある。

 バッファプールへの割り当てが足りない。という事。

という事でググってみると、主に2つの解決策があるみたい。

 

 

対処法

  1. swap領域を作成する
  2. innodb_buffer_pool_sizeの割り当てを増やす

というのが、主な解決策らしい。

参考サイト: https://kenzo0107.hatenablog.com/entry/2016/05/20/105756

 

 

基本的な用語の理解

初学者なので、ここでいったん整理しておく。

「そんなん知ってるわ」っていう方は見なくていいと思います。

 

まず、対処法1の「swap領域を作成する」ということについて。 

そもそも、

 

swapとは

使ってないメモリの内容を一時的にしまっておくための場所。

 

swap領域とは

メモリの内容を一時的にしまっておく場所のこと。

 

ちなみに、

メモリの内容を一時的にしまっておくファイルを「スワップファイル」。

メモリの内容を一時的にしまっておくパーテーションを「スワップパーテーション」。

というらしいです。

swapに関しては下記サイトが図も交えつつ、ある程度ザックリまとまっていて分かりやすかったです。

https://wa3.i-3-i.info/word1721.html

 

 

 で、対処法2のinnodb_buffer_pool_sizeの割り当てを増やすということについて。

 

innodb_buffer_pool_sizeとは

MySQLinnodb_buffer_pool_sizeは、ディスクイメージをメモリ上にバッファさせる値をきめる設定値で、この設定が、いかにディスクIOを押さえるかに繋がったりするので、コストパフォーマンス向上を考えるうえで重要な設定のひとつだったりします。

https://corporate.inter-edu.com

 

innodbとは

MySQLmariaDBにおけるデータベースエンジン。とのこと。

 

バッファとは

バッファ(Buffer)とは、一時的にデータを蓄えておく記憶装置や記憶領域のことです。 バッファは、緩衝物や緩衝装置と訳されますが、コンピュータの業界では、主にデータを一時的に蓄えておく記憶装置や記憶領域のことを指します。

https://www.secomtrust.net/secword/buffer.html

 

 

原因と対処法の整理

つまり、先ほどのエラーログで出ていた「 バッファープールへの割り当てが足りない」とログに出ていたということは、エラーは

原因: 「割り当てられているメモリの量がたりない」

対処法:  使わないメモリを一時的に退避させる場所を作るか(swap領域の作成)、メモリの割り当てを増やす(innodb_buffer_pool_sizeの割り当てを増やす)

ということになる。

 

 

対処法の具体的な手順

これはググると、たくさん出てくると思うが、一応自分が実際行った手順を備忘録がてら残しておく。

 

swap領域を作成する 

まず、ディスクの利用状況を確認

[ec2-user@ip-10-0-0-191 ~]$ df -h

ファイルシス   サイズ  使用  残り 使用% マウント位置

devtmpfs         482M     0  482M    0% /dev

tmpfs            492M     0  492M    0% /dev/shm

tmpfs            492M  512K  492M    1% /run

tmpfs            492M     0  492M    0% /sys/fs/cgroup

/dev/xvda1       8.0G  6.1G  2.0G   76% /

tmpfs             99M  4.0K   99M    1% /run/user/1000

 

空ファイル作成

[ec2-user@ip-10-0-0-191 ~]$ sudo dd if=/dev/zero of=/swapfile bs=1M count=1024

1024+0 レコード出力

1073741824 バイト (1.1 GB) コピーされました、 15.7396 秒、 68.2 MB/

 

作成したファイルをswap領域に設定

[ec2-user@ip-10-0-0-191 ~]$ sudo mkswap /swapfile

mkswap: /swapfile: パーミッション 0644 は安全な値ではありません。 0600 をお勧めします。

スワップ空間バージョン 1 を設定します。サイズ = 1024 MiB (1073737728 バイト)

ラベルはありません, UUID=9940e6a8-3ed3-4175-8f33-8efe191aa13d

 

パーミションを変更

[ec2-user@ip-10-0-0-191 ~]$ sudo chmod 600 /swapfile

 

swap領域を有効にする

[ec2-user@ip-10-0-0-191 ~]$ sudo swapon /swapfile

 

メモリの利用状況を確認

[ec2-user@ip-10-0-0-191 ~]$ free

total        used        free      shared  buff/cache   available

Mem:        1006896      725588       62752         524      218556      141904

Swap:       1048572           0     1048572

 

MySQLを再起動

 

[ec2-user@ip-10-0-0-191 ~]$ sudo service mysqld restart

Redirecting to /bin/systemctl restart mysqld.service

 

 

上記コマンドだけだと、再起動した際にマウントされないらしいので、 /etc/fstab に

/swapfile swap swap defaults 0 0

を追加。

 

 

innodb_buffer_pool_sizeの割り当てを増やす 

MySQLに入る

[ec2-user@ip-10-0-0-191 etc]$ mysql -u root -p

(パスワードの入力)

 

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)

 

my.cnfの場所を探す

[ec2-user@ip-10-0-0-191 etc]$ mysql --help | grep my.cnf

                      order of preference, my.cnf, $MYSQL_TCP_PORT,

/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 

 

左から順に探していき、該当するファイルがあればそれに設定を書き込む

[ec2-user@ip-10-0-0-191 etc]$ sudo vi my.cnf

 

以下を追記

innodb_buffer_pool_size = 256M

 

MySQLを再起動

[ec2-user@ip-10-0-0-191 ~]$ sudo service mysqld restart

Redirecting to /bin/systemctl restart mysqld.service 

 

innodb_buffer_pool_sizeを調べる

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

+-------------------------+-----------+

| Variable_name           | Value     |

+-------------------------+-----------+

| innodb_buffer_pool_size | 268435456 |

+-------------------------+-----------+

1 row in set (0.00 sec)

 

以上。

 

余談ですが、過去の自分のような初学者の方は

手順が書いてある個人のブログを鵜呑みにして、それ通り行いがちですが、ブログの記事を鵜呑みにせず(この記事含め)構造的に原因と対処を捉えた方が結果的に解決が早いと思うので、

・なるべく公式サイトなどで解決できそうな文献が見つけらたら、それを参考にする。

・文献が見つけられず、個人のブログなどを参考にする場合は構造的に理解できる記事を集めて、原因を自分で理解した上で対処する

というのを意識するといいと思います。余談でした。

 

その他参考にしたサイト

https://yusuke.blog/2017/12/17/2029

https://qiita.com/madaran0805/items/ae0532a7436e1c684e72

https://dacelo.space/mysql/entry-1116.html

https://soudan.hatenablog.jp/entry/mysql-bufferpoolsize