MySQLで「the user specified as a definer ('mysql.infoschema'@'localhost') does not exist」というエラーが出る



## はじめに
開発環境にDockerを導入しようとして、なんやらかんやらいじっていたら、タイトルのエラーが出るようになってしまいました。
具体的には、以下のようなことをすると、タイトルのエラーメッセージが表示されるようになりました。
・rails serverを起動して、ローカルにアクセスする
・MySQLを起動してshow databasesなどのクエリを実行する
~~~
mysql> show databases;
the user specified as a definer ('mysql.infoschema'@'localhost') does not exist
~~~
今回は、このエラーを解決するまでの手順と、その途中で出くわした問題などを、自分の備忘録として、かつ同じ問題に遭遇した方へ少しでも助けになれるようにと思い、書き残していきます。


## 「mysql.infoschema'@'localhost」というユーザーを作成する

最初に、「the user specified as a definer ('mysql.infoschema'@'localhost') does not exist」というエラーをググってみると、どうやら **「mysql.infoschema'@'localhost」というユーザーが存在しないこと** が原因であるため、 **「mysql.infoschema'@'localhost」を作成し、権限を付与する** ことで解決しそうだとわかりました。

そこで、
https://stackoverflow.com/questions/62127983/error-1449-hy000-the-user-specified-as-a-definer-mysql-infoschemalocalho
を参考に、まずは「mysql.infoschema’@‘localhost」というユーザーを作成しました。

~~~
mysql -u root -p
~~~
でログインし、
~~~
mysql> use mysql;
  Database changed
~~~
データベースを変更し、
~~~
mysql> CREATE USER 'mysql.infoschema'@'localhost' IDENTIFIED BY 'password';
~~~
ユーザーを作成します。
 ＊passwordは各自で変更して下さい


ところが、次に権限を付与しようとすると
~~~
mysql> GRANT SELECT ON *.* TO `mysql.infoschema`@`localhost`;
　　　　access denied for user 'root'@'localhost' (using password: yes)
~~~

というエラーが発生し、権限の付与ができませんでした、、、

### 新たな問題１　「mysql.infoschema'@'localhost」に権限が付与できない

~~~
access denied for user 'root'@'localhost' (using password: yes)
~~~
というエラーは様々な場面で出てくるようですが、今回の状況では、**rootユーザーが「他のユーザーに権限を付与するための権限」を持っていないこと**が原因らしいとわかりました。（Dockerを導入しようとしていろいろといじっているうちに、rootユーザーの削除・再作成などをやってしまったのかもしれません、、、）
そのため、まずは **rootユーザーに「権限を付与するための権限」を与える** ことにしました。


## セーフモードでMySQLを起動しrootユーザーに権限を付与する

https://killtime.blog/revive-deleted-root-user-on-mysql8/
上記のサイトを参考にさせていただきました。

rootユーザーに権限を付与するためには、権限を無視するセーフモードで起動する必要があるようなので、まずはセーフモードでMySQLを起動します。

~~~
mysqld_safe --skip-grant-tables
~~~

:::note info
＊＊ちなみに、私の場合はこの時点で
~~~
mysqld_safe A mysqld process already exists
~~~
というエラーが発生し、MySQLが起動できませんでした、、、
詳細は後述しますので、同じ問題に直面した方はそちらをご参照ください。
:::

次に、
~~~
mysql> use mysql;
  Database changed
~~~
でデータベースを変更し、
~~~
mysql> select* from user; 
~~~
で各ユーザーの状態を確認しました。

すると、rootユーザーの「権限を付与するための権限であろう **Grant_priv**」がNとなっていたため、
~~~
mysql> update user set Grant_priv = "Y" where user = “root";
~~~
でrootユーザーに権限を付与しました。

~~~
mysql> update user set Grant_priv = "Y" where user = "root";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
~~~

最後に、
~~~
mysql> flush privileges;
~~~
で変更を反映させ、一度quitでMysqlから抜けました。

### 新たな問題２　セーフモードでMySQLを起動することができない

先程の手順の中で、
~~~
mysqld_safe --skip-grant-tables
~~~
によってMySQLをセーフモードで実行するところがありましたが、その際に私のケースでは
~~~
mysqld_safe A mysqld process already exists
~~~
というエラーが発生し、MySQLを起動することができませんでした。
調べてみたところ、 **以前に起動したmysqldのプロセスが残っていることが原因**とのことでした。

そこで、
~~~
ps aux | grep mysqld
~~~
で実行中のmysqldに関するプロセスを取得し、
~~~
kill -9 プロセスid
~~~
でプロセスを強制終了させた後、再度
~~~
mysqld_safe --skip-grant-tables
~~~
を実行することで、セーフモードで起動することができました。

##### 今後もこのようなことが起こらないために、最後にセーフモードのプロセスを終了させることを忘れないよう心に刻みます。


### 新たな問題３　MySQLに接続できない

rootユーザーへの権限付与が完了したので、rootユーザーでログイン後に「mysql.infoschema'@'localhost」に権限を付与しようとして
~~~
mysql -u root -p
~~~
を実行したところ、
~~~
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
~~~
というエラーが出て、MySQLに接続することができませんでした。

ところがこの問題の原因は単純で、 **単にMySQLサーバーが起動していないだけ**でした、、、おそらく、mysqldに関するプロセスを終了させる際に、サーバーも停止してしまったのではないかと思います。

そこで、
~~~
mysql.server start
~~~
~~~
mysql -u root -p
~~~
を実行することで無事にログインができました。


## mysql.infoschema’@‘localhostに権限を付与する

MySQLに接続し、この時点でshow databases;などのクエリを実行したところ、
~~~
mysql> show databases;
ERROR 1356 (HY000): View 'information_schema.SCHEMATA' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
~~~
というエラーが発生しました。
当初の
~~~
mysql> show databases;
the user specified as a definer ('mysql.infoschema'@'localhost') does not exist
~~~
というエラーからは変化しているので、**「mysql.infoschema'@'localhost」というユーザーが存在しないという問題**は解決できているようですが、**「mysql.infoschema'@'localhost」に権限が付与されていないという問題**が残っているようです。

そこで、
~~~
mysql> GRANT SELECT ON *.* TO `mysql.infoschema`@`localhost`;
~~~
で「mysql.infoschema'@'localhost」に権限を付与します。

~~~
mysql> GRANT SELECT ON *.* TO `mysql.infoschema`@`localhost`;
Query OK, 0 rows affected (0.01 sec)
~~~

この時点で、show tablesなどのクエリを実行すると、無事にテーブル一覧が表示されるようになりました！
また、rails serverを起動してローカルに接続することにも成功しました！

最後に、残っているセーフモードのプロセスを終了させます。
~~~
ps aux | grep mysqld
~~~
~~~
kill -9 プロセスid
~~~

## おわりに

以上が「the user specified as a definer ('mysql.infoschema'@'localhost') does not exist」というエラーを解決するまでの手順になります。
間違っているところやおかしな部分などがありましたら、ぜひお教えください。

この記事が少しでもお役に立てることを願っています。ご覧いただきありがとうございました。