かすみん日記

暇なときに何か喋ります

【作業ログ】MySQLのインストール・初期設定

MySQLをインストールしたときの作業ログです。

Progateの記事が参考になります。

prog-8.com

環境

  • macOS Monterey
  • インテル入ってる
  • MySQL 8.0
    • バージョンによる違いが結構あるようなので注意

インストール

Homebrewでインストールします。

パッケージがあるか確認:

% brew search mysql
==> Formulae
automysqlbackup          mysql++                  mysql-client@5.7         mysql-sandbox            mysql@5.6                mysqltuner
mysql                    mysql-client             mysql-connector-c++      mysql-search-replace     mysql@5.7                qt-mysql

==> Casks
mysql-connector-python        mysql-shell                   mysqlworkbench                navicat-for-mysql             sqlpro-for-mysql

ありました:

% brew info mysql
mysql: stable 8.0.29 (bottled)
Open source relational database management system
https://dev.mysql.com/doc/refman/8.0/en/
Conflicts with:
  mariadb (because mysql, mariadb, and percona install the same binaries)
  percona-server (because mysql, mariadb, and percona install the same binaries)
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/mysql.rb
License: GPL-2.0-only with Universal-FOSS-exception-1.0
==> Dependencies
Build: cmake ✘, pkg-config ✔
Required: icu4c ✘, libevent ✔, libfido2 ✘, lz4 ✔, openssl@1.1 ✘, protobuf ✘, zstd ✘
==> Caveats
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To restart mysql after an upgrade:
  brew services restart mysql
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/mysql/bin/mysqld_safe --datadir=/usr/local/var/mysql
==> Analytics
install: 114,189 (30 days), 276,044 (90 days), 1,041,048 (365 days)
install-on-request: 113,807 (30 days), 275,331 (90 days), 1,037,696 (365 days)
build-error: 331 (30 days)

インストールします:

brew install mysql

インストールできたか確認:

% which mysql
/usr/local/bin/mysql

% mysql --version
mysql  Ver 8.0.30 for macos12.4 on x86_64 (Homebrew)

実行確認

まずはMySQLのサーバーを立てる:

% mysql.server start
Starting MySQL
. SUCCESS! 

MySQL monitor(対話形式のやつ)を起動:

% mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.30 Homebrew

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

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>

サーバー立てるのを忘れていると、以下のようなエラーメッセージが表示される(はず):

% mysql
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

ちゃんと起動したら、試しにselect文でも実行してみる。

かけ算:

mysql> select 6 * 4;
+-------+
| 6 * 4 |
+-------+
|    24 |
+-------+
1 row in set (0.00 sec)

ユーザーリスト取得:

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

既存データベース確認:

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

対話モードから抜けるにはexitを実行する:

mysql> exit
Bye

初期設定

mysql_secure_installation

上のProgateの記事にも、まずmysql_secure_installationコマンドを実行してセキュリティあーだこーだしろって書いてあります。

mysql_secure_installationは最低限のセキュリティ設定をしてくれるものらしいです。

例えば、匿名ユーザを削除したり、rootユーザのパスワードを設定したりとかです。

あとは、バージョンによる差異(設定の仕方とか)も吸収してくれるらしいです。

今回はこれを使用せず、手動で設定をしてみます。

下記記事も参照してください:

qiita.com

初期DBの確認

存在しているデータベースはshow databases;コマンドで確認できます:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

インストールした時点で、4つのDB(スキーマ?)がありました。

各DB内のテーブルを確認するには、use db_nameコマンドのあとshow tables;コマンドを実行すればよいです。例えば:

use mysql
show tables;

初期ユーザの確認

インストールした時点で何人かユーザがいます:

mysql> select user, host, authentication_string from mysql.user;
+------------------+-----------+--------------------------+
| user             | host      | authentication_string    |
+------------------+-----------+--------------------------+
| mysql.infoschema | localhost | 長い文字列                 |
| mysql.session    | localhost | 長い文字列                 |
| mysql.sys        | localhost | 長い文字列                 |
| root             | localhost |                          |
+------------------+-----------+--------------------------+

昔のバージョンではpasswordという列が存在していたようですが、MySQL 8.0では存在していませんでした。

どうやらpassword列はauthentication_string列へと移行したようです。

匿名ユーザ(user列が空白のレコード)は存在していませんが、rootユーザのパスワードは空白となっていました。

なので、単にmysql実行時や、mysql -u root -pでパスワードを聞かれたときに何も入力せずエンター押下した際には、そのままrootユーザでログインできてしまいます。

パスワード設定

rootユーザにパスワードを設定します。初期では空白''でした。

上で見た通り、ユーザのパスワードはmysqlデータベースのuserテーブルのauthentication_string列に保存されていました。

なので、普通にupdate文でデータ更新すればと思ったが、password_last_changed列などもあるので何かしら関数を使った方が良さげ。

関数というか、alter user文でパスワードの更新を行う。

ALTER USER 'root'@'localhost' identified BY 'パスワード';

実行後、authentication_string列に何かしらの長い文字列が挿入され、password_last_changed列(パスワード更新日時)も現在の日時に更新された:

mysql> select user, host, password_last_changed from mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | password_last_changed |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | 2022-08-09 08:51:28   |
| mysql.session    | localhost | 2022-08-09 08:51:28   |
| mysql.sys        | localhost | 2022-08-09 08:51:28   |
| root             | localhost | 2022-08-10 00:56:10   |
+------------------+-----------+-----------------------+

一旦ログアウトして、パスワード無しでログインしようとすると、今度は怒られる:

mysql> exit
Bye

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

% mysql -u root -p
Enter password:   # 何も入力せずエンター
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

上で設定したパスワードを入力すると、ちゃんとログインできた:

% mysql -u root -p
Enter password:   # 上で設定したパスワードを入力してエンター
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 8.0.30 Homebrew

試しにパスワードを空白''に戻してみたら、初めの状況に戻った:

ALTER USER 'root'@'localhost' identified BY '';

あと、5系の記事でよく見るpassword()関数は8系では使えないようです?

初期設定は以上。

不具合対処

以下では、エラー対応やらなんやらの備忘録になります。

どうやら私は、昔にMySQLをインストールしたことがあるようです。

上のProgateの記事もvisitedでしたし。

それで、おそらくそれが原因で色々不具合があったので、対処法?をまとめておきます。

エラー1

% mysql.server start
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/マシン名.pid).

原因はよくわからない。

とりあえず以下の作業でこのエラーは出なくなったが、再現性がないので原因を特定できず。

古いバージョンを昔に使っていたことがあると、MySQL 8.0と競合しちゃう的な?

愚直な対応として、/usr/local/var/mysql/ディレクトリを削除してからMySQLを再インストールしました。

brew uninstall mysqlしてもディレクト/usr/local/var/mysql/は自動削除されないようなので、まずは手動でこれを削除します:

rm -r /usr/local/var/mysql/

そのあと、MySQLをアンインストール&インストールします:

brew uninstall mysql
brew install mysql

brew reinstallで良かったかも)

これで、初めに書いたエラーは出なくなったのですが、別のエラーが出るようになったので継に続く。

エラー2

% mysql.server start 
Starting MySQL
 SUCCESS! 

% 2022-08-09T00:01:33.6NZ mysqld_safe A mysqld process already exists
# ↑勝手に挿入、入力待ち

なんかmysqldプロセスは既に存在していると書いてある。

じゃあstopしてみるか:

% mysql.server stop        
Shutting down MySQL
.. SUCCESS! 

成功したと書いてるが、もう一度mysql.server startしても同様の症状となる。

これは、既にbrew services start mysqlが走っていることが原因。

再現もできたので、これが原因で間違いないと思う。

というわけで、これを終了させる:

% brew services stop mysql 
Stopping `mysql`... (might take a while)
==> Successfully stopped `mysql` (label: homebrew.mxcl.mysql)

このサービスが走っていなかった場合は、下記のような表示になる:

% brew services stop mysql
Warning: Service `mysql` is not started.

どうして既にbrew services start mysqlが走っていたかは謎。 brew install mysqlしたら自動でサービスが起動するとかではない(これは再インストールして確認した)。

おそらく、昔にインストールしたときに、これを走らせたまま今の今まで忘れていた?

試行錯誤ログ

後になってみれば、上で書いた2つの原因だけだったが、途中試行錯誤したときのメモを残しておく。

プロセス確認

mysqldプロセスが走っているかの確認:

% ps aux | grep mysqld                  
username           10644   0.0  0.0 33598524    800 s001  S+   10:18AM   0:00.00 grep mysqld

この結果であれば、今実行中のgrep mysqldが表示されているだけなので、他には走っていない。

他にプロセスが走っていれば、以下のようになる:

% ps aux | grep mysqld 
username            5141   0.1  2.3 34802212 389808   ??  S     8:51AM   0:02.81 /usr/local/opt/mysql/bin/mysqld --basedir=/usr/local/opt/mysql --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/opt/mysql/lib/plugin --log-error=nyaa.err --pid-file=nyaa.pid
username            5512   0.0  0.0 33607740    820 s001  S+    9:04AM   0:00.00 grep mysqld
username            5053   0.0  0.0 34134528   1520   ??  S     8:51AM   0:00.03 /bin/sh /usr/local/opt/mysql/bin/mysqld_safe --datadir=/usr/local/var/mysql

プロセスを終了するには、kill -9 プロセスIDコマンドを実行する。

プロセスIDは、左から2列目の4桁の数字。これを指定すればよい:

kill -9 5141
kill -9 5053

なお、このプロセス状況では、/bin/sh /usr/local/opt/mysql/bin/mysqld_safeのプロセスを終了したら、勝手に/usr/local/opt/mysql/bin/mysqldの方も終了した。

この状況は、mysql.server startあるいはbrew services start mysqlを実行すれば再現できる。

前者の場合はmysql.server stopで、後者の場合はbrew services stop mysqlでプロセス終了できる。

brew services start mysqlで起動したプロセスをmysql.server stopで終了することはできない。逆もまた然り。

pidファイル

mysql.server startまたはbrew services start mysqlが走ってる間、usr/local/var/mysql/以下にマシン名.pidファイルが生成される。

stopすると、pidファイルは削除される。

マシン名はumane -nコマンドで確認できる。

下記コマンドで結果が返ってきたら、そのpidファイルが存在している:

ls usr/local/var/mysql/$(uname -n).pid

参考

prog-8.com

qiita.com

ja.stackoverflow.com

dkssksk.com

qiita.com

yaba-blog.com

qiita.com

https://qiita.com/busitora2/items/5b93c12f8964a7eae316