Laravel+MySQL8.0環境でマイグレートできない場合の原因と対処法

2020年2月23日 21:01

はじめに

PHPのフレームワークであるLaravelを使ってWebアプリを開発しているときにエラーが出力されたので、原因と解決方法を残します。

事象

マイグレーションファイルを作成しマイグレートを実行したところ、以下のエラーが出力されました。

$ php artisan migrate

   Illuminate\Database\QueryException  : SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = laravel and table_name = migrations and table_type = 'BASE TABLE')

  at /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669
    665|         // If an exception occurs when attempting to run a query, we'll format the error
    666|         // message to include the bindings with SQL, which will make this exception a
    667|         // lot more helpful to the developer instead of just the database's errors.
    668|         catch (Exception $e) {
  > 669|             throw new QueryException(
    670|                 $query, $this->prepareBindings($bindings), $e
    671|             );
    672|         }
    673| 

  Exception trace:

  1   PDOException::("PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password]")
      /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70

  2   PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=laravel", "root", "secret", [])
      /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70

  Please use the argument -v to see more details.

調査

まず、DB設定を確認してみます。.envは以下のようになっています。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=secret

実際にこの設定でMySQLに接続できるか試行してみます。

$ mysql -uroot -p -h 127.0.0.1 -P 3306
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 8.0.19 Homebrew

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

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

正常に接続でき、データベースも存在していることが確認できました。

原因

MySQLのバージョンが8.0.4以降の場合、デフォルトの認証方式がcaching_sha2_passwordになっており、PHPのMySQL接続ライブラリがcaching_sha2_passwordに対応していないため、MySQLに接続できない(ログインできない)というエラーが発生していました。

対処

認証方式をcaching_sha2_passwordからmysql_native_passwordに変更します。
まず、現在の認証方式を確認しておきます。

mysql> select user, host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)

認証方式を変更するには以下を実行します。

mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'secret';
Query OK, 0 rows affected (0.01 sec)
mysql> select user, host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | mysql_native_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)

恒久対処

新しいユーザーを作成するときのデフォルトの認証方式を設定します。
まず、デフォルトの認証方式を確認しておきます。

mysql> show variables like 'default_authentication_plugin';
+-------------------------------+-----------------------+
| Variable_name                 | Value                 |
+-------------------------------+-----------------------+
| default_authentication_plugin | caching_sha2_password |
+-------------------------------+-----------------------+
1 row in set (0.02 sec)

デフォルトの認証方式を変更するには以下のように設定します。
※以下はmacOSにHomebrewでMySQLをインストールした場合の一例です。my.cnfの場所は適宜読み替えてください。

$ vi /usr/local/etc/my.cnf

[mysqld]
default_authentication_plugin=mysql_native_password

設定を変更したらMySQLを再起動します。

$ mysql.server stop
$ mysql.server start

もう一度設定を確認します。

mysql> show variables like 'default_authentication_plugin';
+-------------------------------+-----------------------+
| Variable_name                 | Value                 |
+-------------------------------+-----------------------+
| default_authentication_plugin | mysql_native_password |
+-------------------------------+-----------------------+
1 row in set (0.00 sec)

関連記事

開発環境(ローカルストレージ)と本番環境(Amazon S3)にトリミング+リサイズした画像を保存する方法
# はじめに 以前、以下の記事を書きました。 - [開発環境と本番環境で画像のアップロード先を分岐する方法 \- AUTOVICE](https://www.autovice.jp/articles/68) - [ローカルやAmazon [...]
2020年3月7日 11:56
Laravel Mixの仕組みをわかりやすく解説:CSSをSASS/SCSSで記述する方法
# はじめに Laravel Mixの仕組みをわかりやすく解説します。Laravel Mixを使ってアセットコンパイルを行うことで、SASS/SCSSでCSSを記述できるようになります。 # Laravel Mixの仕組み まずはじめに、 [...]
2020年3月6日 9:25
【Laravel 6.x】Laravelプロジェクトの名称を変更する方法
# はじめに あまりないケースではありますが、一度作成したLaravelプロジェクトの名称を変更する方法を解説します。ここで言うLaravelプロジェクトの名称とは、以下のコマンドの`Sample`のことを指します。 ```terminal [...]
2020年3月4日 16:24
【Laravel】ローカルディスクやAmazon S3にアップロードした画像をビューで表示する方法
# はじめに 本記事では、ローカルディスクやAmazon S3にアップロードした画像をビューで表示する方法について説明しています。 なお、本記事では画像のアップロードする方法については説明していません。本記事は既に実装済みの画像アップロード [...]
2020年3月4日 15:44
【Laravel】Amazon S3へのアップロードが「403 Access Denied」で失敗する原因と対処方法
# はじめに LaravelでAmazon S3へ画像アップロードする処理を実装し、いざアップロードしようとしたところ、以下のエラーが出て失敗しました。 ``` Error executing "PutObject" on "https: [...]
2020年3月4日 13:33