subtitle

RaiseTechの各種コースをはじめとしたイロイロな学習の記録

MySQLをRailsで使えるようにするのに非常に苦労した話

以前に、EC2上のRailsアプリを作成する際に、デフォルトのSQLite3をデータベースにしちゃったから、それをMySQLに変更するために、mysql2というgemをインストールするのにマジハマりしたというお話をしましたが・・・。


またまた、どハマりました。

今度はMySQL(データベース)で。


いや、でもこれ、自分がMySQLについて(というか、データベースについて)あまりにも無知すぎて、マジでビビったww


そもそもの発端は、自分がmysqlとMySQL、データベースのクライアントとサーバーをごっちゃにしていたところにある。


Railsで使うデータベースは、rails newコマンドの時に -d オプションで指定しなければSQLite3になるし、 -d mysql などにすればMySQLになる。

が、これってあくまでもクライアントとしてのデータベースの指定であるということに、さっき気づいたんだよーーー!!!(死)


てかさ、一番悪いのはSQLite3だ!(←人(DB)のせいにするw)

SQLite3は、サーバーレスのデータベースなのだった。それをインストールしさえすれば、即使えるのだ。SQLiteデータベースは、単一のディスクファイルだから、データベースエンジンが必要ない。

だから、rails newしたら、即データベースも使えたのであった。


最初にこれ使ったら、rails newしたらすぐデータベース使えるって思っちゃうよね!

(ちゃんと考えずに使っていた自分を棚に上げる。)


今回、Serverspecの自動テストを試してみたくて、EC2内部にデータベース(MySQL)を持つ環境を作ろうと思って、RailsアプリをMySQL指定で作成したのさ。

したらば、データベースにアクセスできない!!ってなって(当たり前だw)、なんで!?と悩んだのでありました。


mysqlはインストールされている、がmysqldは起動していない。

というとことまで分かっていたのだが、なぜrails newの時にデータベースサーバーがインストールされていなかったのかという点には気づいていなかったのだ。(データベースサーバーまで勝手にインストールされて、すぐに使えるようになると思い込んでいたわけです。QLite3のように!)


rails newでインストールされるmysql2は、あくまでもクライアントとして、サーバーにリクエストするために必要な機能やライブラリであって、データベースエンジンはそれとは別にインストールする必要がある。


EC2上に直接データベースを置いて、Railsアプリからアクセスできるようにする方法

今回は、AWS上に手動で作成したEC2(Amazon Linux2)インスタンス上で実施している。

rails new コマンドでRailsアプリを作成する。

rails new spectest_apl -d mysql



MySQLをインストールする

システムのパッケージを更新する

sudo yum update


MariaDBのパッケージを削除。MySQLはMariaDBと互換性がないため、MariaDBを削除せずにMySQLをインストールしようとすると、結局MariaDB消せって怒られるっぽい。(から先に消しとく)

sudo yum remove mariadb-libs


yumにMySQLのリポジトリを追加

mysql80-community-release(MySQL 8.0.x)がインストールされる

sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm


mysql-community-server(8.0.23)をインストールする

sudo yum install --enablerepo=mysql80-community mysql-community-server


mysql-community-devel(8.0.23)をインストールする

sudo yum install --enablerepo=mysql80-community mysql-community-devel


一応インストールされたもの一覧を確認しておく

yum list installed | grep mysql

※上記は、インストールされたもの一覧から、mysql関連でグレップしたものを出力

mysql-community-client.x86_64         8.0.23-1.el7                   @mysql80-community
mysql-community-client-plugins.x86_64 8.0.23-1.el7                   @mysql80-community
mysql-community-common.x86_64         8.0.23-1.el7                   @mysql80-community
mysql-community-devel.x86_64          8.0.23-1.el7                   @mysql80-community
mysql-community-libs.x86_64           8.0.23-1.el7                   @mysql80-community
mysql-community-server.x86_64         8.0.23-1.el7                   @mysql80-community
mysql80-community-release.noarch      el7-3                          installed


ログが出力されるファイルを予め作成しておく

sudo touch /var/log/mysqld.log


試しに、バージョンも表示させてみるか

mysqld --version
# /usr/sbin/mysqld  Ver 8.0.23 for Linux on x86_64 (MySQL Community Server - GPL)

うん、OK!

mysql --versionとmysqld --versionの違いを理解していなかったんだよなぁ~・・・

今ならわかる。mysqlはクライアント側、mysqldがサーバー側。




MySQLサーバーを起動する

起動コマンド

sudo systemctl start mysqld


mysqldのステータスを確認しておく

systemctl status mysqld.service

runningになっているのでOK

 mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2021-03-26 07:20:40 UTC; 8s ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 31260 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 31335 (mysqld)
   Status: "Server is operational"
   CGroup: /system.slice/mysqld.service
           mq31335 /usr/sbin/mysqld

Mar 26 07:20:34 ip-172-16-16-180.ap-northeast-1.compute.internal systemd[1]: ...
Mar 26 07:20:40 ip-172-16-16-180.ap-northeast-1.compute.internal systemd[1]: ...
Hint: Some lines were ellipsized, use -l to show in full.



MySQLにログインする

さあ、いざMySQLにログインしようとした矢先・・・

mysql -u root -p

イキナリ怒られる理不尽なわたし

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)


調べてみると、MySQL8はログイン認証のプラグインが変わったらしく、現在のユーザーとログインしようとしているユーザーが異なるとログインできないらしい。(ナニソレ!)


認証処理をスキップする

ログインできないのでは、お話にならないので、認証処理をスキップしてDBにアクセスする。

まずはMySQLを停止させる

sudo systemctl stop mysqld


認証処理をスキップするセーフモードの起動には、mysqld_safe --skip-grant-tables というコマンドがあるらしいが、自分の環境では使えないようなので、別の方法で試してみる。

環境変数を設定

sudo systemctl set-environment MYSQLD_OPTS="--skip-grant-tables"


MySQLを開始

sudo systemctl start mysqld


気を取り直して、再度MySQLにログイン!

mysql -u root

やっとつながった・・・(長かった!!)


rootユーザーのパスワードを変更する

さあ、これでようやくrootユーザーのパスワードを変更することができるぜ!


mysqlデータベースを使用

mysql> use mysql;


rootユーザーのパスワードはなし(null)に設定

mysql> UPDATE mysql.user SET authentication_string=null WHERE User='root';

これで、パスワードなしのrootユーザーが設定された


exitコマンドでMySQLからログアウトしたら、今度は先ほど設定した環境変数を元に戻す

sudo systemctl unset-environment MYSQLD_OPTS


設定完了したので、MySQLを再起動

sudo systemctl restart mysqld.service


パスワードなしのrootユーザーでログインする

mysql -u root


キタ――(゚∀゚)――!!――(゚∀゚)――!!


ひとまずまず何もないDBを表示してみよう

mysql> show databases;


む?また怒られたよ

ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.


パスワードリセットしなさいよ、というお叱りが!(めんどくさいぜ!)

ALTER USER使って変えろって言われているから、素直に従う

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'パスワード';

※パスワードの制約が結構厳しくて、大文字小文字英数字記号入れて8文字以上みたいな感じ


パスワード変更が許可されたら、データベースが使えるようになる

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)


うむ。よきかな。

続いて、config\database.ymlのパスワードも忘れずに変更しておく

※これ忘れると、次にmysqlでログインできなくなるよ!

default: &default
  adapter: mysql2
  encoding: utf8mb4
  database: mysql
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: ここにパスワード
  host: localhost


データベースもちゃんと作成できるようになりました!

rails db:create
rails db:migrate


と、言うわけで、ようやくEC2上のRails環境からデータベースにアクセスする準備が整ったのでした。