RaspberryPi3を買った時。そう3年前。

MySQLを入れようと、aptでインストールしてみると実態はMariaDBという現実。


仕事で使っているのはMySQL、そして世の中はどちらかというとMySQLで溢れていて。

ラズパイでもMySQLを使うんだ。そう意気込んだ3年前、そうあれはゴールデンウイーク。

コンパイルに負けて挫折して、"Gold"en WeeKは"Gray" Weekになって

でも略してもGWになるんだね、はは(白い目


だけど

世の有志の手によるdebファイルに救われて。

ラズパイにMySQL5.7を入れることは出来た。


でも僕は。

負けたのだ。

何かに。


あれから3年。

ラズパイは4になり、RaspbianもBusterベースになり、かたやMySQLも8にバージョンアップして。

そして僕も(願望)。




喉に引っ掛かった小骨を取るように、今回ラズパイでMySQLをコンパイルしてみます。



1.準備

今回の環境とターゲットとなるMySQLは以下となります。

  • RaspberryPi4 4GB
  • Raspbian Buster(Raspbian GNU/Linux 10 \n \l)
  • Kernel version:5.4.50-v7l+
  • gcc version 8.3.0 (Raspbian 8.3.0-6+rpi1)
  • MySQL8.0.20

さて、まずはrootになります。

$ su - root
パスワード:
#

rootユーザーにスイッチできない場合は、多分rootユーザーに対してパスワードが設定されていないから。

以下の記事を参考にして頂ければ。

Raspberry Pi 4 サーバー構築06 セキュリティ対策編 : DevLife

あとは、mysqld実行時のユーザーとグループをここで作っておこう。

# groupadd mysql
# useradd -r -g mysql -s /bin/false mysql

それから、ついでにvimもインストールしとこう。

# apt install -y vim

2.必要(だと思われる)なライブラリのインストール

以下のコマンドでコンパイル時に必要なライブラリをインストールする。

# apt install libncursesw5-dev \
libncurses5-dev \
cmake \
build-essential \
libssl-dev \
pkg-config \
libssl-dev \
binutils-gold \
libprotobuf17 \
bison \
libsasl2-2 \
libsasl2-dev \
libgsasl7-dev \
libldap2-dev

正直、上記は手探りです。

cmakeでエラーになるたびにログみて多分このパッケージかな?とか考えながらinstallしていったので、本当は上記で指定したパッケージインストール時に関連性で同時にインストールされるパッケージのほうが実は必要なライブラリだったり、とかはあるかも。いや絶対ある。

というわけで、ぶっちゃけここで3日ほど消化。

3.MySQL8ソースコードのダウンロード

2020/07/07時点で最新のmysql8.0.20のtarボールをダウンロードしてきます。

その後、解凍して出来たディレクトリに入りビルド用のディレクトリbuildの作成、あとはこのbuildディレクトリの中で作業をしていきます。

# pwd
/root
# mkdir tmp
# cd tmp
# wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20.tar.gz
# tar zxvf mysql-8.0.20.tar.gz
# cd mysql-8.0.20/
# mkdir build
# cd build/

追記

今(2020/07/17)サイト覗いたら8.0.21がリリースされてましたwwwちょwww泣くぞwwwwww

新機能としては「Redoログ無効化」が出来るようになって更新処理が高速化できるらしいです。

ただし、Redoログ書き込まなくするとクラッシュリカバリが出来なくなるので、使用場面は初期構築時にデータ移行とかだな。

うん、結構欲しい機能ね。まぁ、ラズパイ上では使わないと思うけど。

うん、でも、やっぱ泣いてくるわwwww

4.(恐怖の)CMAKEする

MySQLコンパイルに関して、広く世に出回っている情報だけでは、ラズパイ上でのmake時の進捗大体37~38%くらい(時間にしてmakeしてから1時間くらい)でundefined symbolで失敗する。

それを回避するヒントは世に出回っているOpenCVコンパイル時のエラー回避方法である-DCMAKE_SHARED_LINKER_FLAGS='-latomic'の指定。

cmakeに上記オプション付けると進捗37~38%くらいで失敗していたのが回避できるんだけど、確か76~78%くらい(時間にしてmakeしてから3時間くらい)で同じくundefined symbolで失敗。

正直、死ねる。

3年前の俺なら死んでた。

正解・・・かどうかは正直分らないんだけど、ラズパイ上でMySQLのmakeを成功に導くcmakeのオプションは以下です。

# cmake ../../mysql-8.0.20 \
-DDOWNLOAD_BOOST=1 \
-DWITH_BOOST=/usr/local/boost \
-DENABLED_LOCAL_INFILE=1 \
-DCMAKE_SHARED_LINKER_FLAGS='-latomic' \
-DCMAKE_C_FLAGS='-latomic' \
-DCMAKE_CXX_FLAGS='-latomic' \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_ja_0900_as_cs \
-DWITH_INNOBASE_STORAGE_ENGINE=1

-DCMAKE_SHARED_LINKER_FLAGS='-latomic'-DCMAKE_C_FLAGS='-latomic'-DCMAKE_CXX_FLAGS='-latomic'がmake時に成功に導く鍵です。・・・正しいのかは分からないけど。

その他のオプション指定としては、-DDOWNLOAD_BOOST=1-DWITH_BOOST=/usr/local/boostで、cmake時にboostライブラリをダウンロードしてきます。

自動で正しいバージョン(MySQL8.0.20に対しては1.70.0、2020/07/17時点の最新は1.73.0だったりする)を落としてきてくれるので、ここだけcmakeすげぇって思える。

あとは、文字コードや照合順序をutf8mb4、utf8mb4_ja_0900_as_csにしています。が、照合順序については、より厳密なutf8mb4_ja_0900_as_cs_ksのほうが面白かったかな?と少し後悔。

日本語用照合順序の情報については、以下を参照してもらうのがよろしいかと。

MySQL 8.0: ひらがなカタカナを判別する日本語用Collation | MySQL Server Blog

[MySQL8.0] デフォルトUTF8MB4、そして新しい日本語用照合順序|ブログ|TOPICS|MySQL

MySQLの文字コードとCollation - Qiita

あとは、指定していないけれども、インストール先はデフォルトの/usr/local/mysqlにしています。

その他のcmakeに関するオプション情報は、MySQL5.6の時のものだけど以下を参照してもらうのがよろしいかと。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 2.9.4 MySQL ソース構成オプション

5.(地獄の)make、make installする

正しくcmake出来ていれば、本当はあまり地獄ではないです。

ただし。えらく時間がかかる!

# make

はい、ここで一旦寝ましょう。

 :

(5時間くらい?)

 :

はい、おはようございます。

モニター見て、ビルド結果見て今日1日の運勢が決まります。ビルドが成功していれば今日は絶好調です。絶好調なはずです。

エラーならば、buildディレクトリをごっそり削除してやり直しです。

ぶっちゃけ、ここで5日を費やしました5日間朝から地獄でした会社休もうかと思いました。

ビルドが成功していれば、あとはインストールするだけです。

# make install

6.MySQLの初期化

ここからは、世の先人たちのノウハウをそのまま使わせて頂きます。

データディレクトリ作成して初期化していきます。

# cd /usr/local/mysql/
# mkdir data
# chown mysql:mysql data
# chmod 755 data

その前に/usr/local/mysql/binにPATHを通しておきます。

# vim /etc/profile

:
PATH=$PATH:"/usr/local/mysql/bin"
export PATH

修正したprofileを今動かしてる環境に反映させます。

# source /etc/profile

そしたら、以下のコマンドでどこのmy.cnfをどういった順序で読みに行くか確認。

# mysql --help | grep my.cnf

order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf

というわけで、/etcの下にmy.cnfを置きます。my.cnfの内容は以下。

# vim /etc/my.cnf

[client]
default-character-set=utf8mb4
port=3306
socket=/usr/local/mysql/data/mysql.sock

[mysql]
default-character-set=utf8mb4

[mysqld]
port=3306
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/data/mysql.sock
user=mysql
default-storage-engine=InnoDB

default_authentication_plugin=mysql_native_password
character_set_server=utf8mb4
collation-server=utf8mb4_ja_0900_as_cs

skip-character-set-client-handshake

[mysqldump]
quick

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/usr/local/mysql/data/mysqld.pid

※注意!my.cnfをちゃんと置いてからデータベースの初期化をしないと、あとでmy.cnf作って設定書いても、その設定が反映されねぇぇぇってなります。

そしたら、データベースを初期化します。

# ./bin/mysqld --initialize --user=mysql
2020-07-16T00:08:15.104028Z 0 [System] [MY-013169] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.0.20) initializing of server in progress as process 6347
2020-07-16T00:08:15.289398Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2020-07-16T00:08:21.657386Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2020-07-16T00:08:33.482005Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: 0S>i(L)Vbhu!

最後に表示された文字列"0S>i(L)Vbhu!"がMySQLのrootのパスワードなのでメモっておきます。

このパスワードは後で変更します。

ちなみに、このパスワードの先頭文字がTeraTermで設定しているフォントTerminalだとアルファベットのオーに見えて、ログイン時にAccess deniedになってログイン失敗して、ビルド失敗疑惑で一瞬泣きそうになったのは内緒です。

まだ安心できないwww

7.サービス登録と自動起動設定

ここも、世の先人たちのノウハウをそのまま使わせて頂きます。

MySQLをsystemctlで操作できるようにサービス登録します。

# cp support-files/mysql.server /etc/init.d/mysqld
# systemctl daemon-reload
# systemctl start mysqld.service
# cp /run/systemd/generator.late/mysqld.service /etc/systemd/system

自動起動設定する前に、systemdで管理されるmysqldユニット定義ファイルに呪文を書き込んでからOS起動時にMySQLも自動起動できるようにする。

# export EDITOR=vim
# systemctl edit mysqld.service

[Install]
WantedBy=multi-user.target

# systemctl enable mysqld.service

呪文については、以下を後で読んで勉強する。

OS起動時にsystemdで行われていること - Qiita

Systemd入門(4) - serviceタイプUnitの設定ファイル - めもめも

8.MySQLへの接続、rootパスワードの変更

いよいよ、MySQLへ接続してみます。

# mysql -u root -p
Enter password:0S>i(L)Vbhu!

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.20

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>

接続出来ました。

rootのパスワードを変更します。

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '[MySQLのrootの新しいパスワード]';
Query OK, 0 rows affected (0.03 sec)

ついでに文字コードを確認。ちゃんとmy.cnfの内容が反映されているかどうか。。。

mysql> show variables like '%char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | utf8mb4                          |
| character_set_connection | utf8mb4                          |
| character_set_database   | utf8mb4                          |
| character_set_filesystem | binary                           |
| character_set_results    | utf8mb4                          |
| character_set_server     | utf8mb4                          |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/mysql/share/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.04 sec)

mysql> quit

ちゃんと反映されてます。

ラズパイを再起動してからMySQLにrootで接続してみます。

# reboot now
:
$ sudo systemctl status mysqld.service
● mysqld.service - LSB: start and stop MySQL
   Loaded: loaded (/etc/init.d/mysqld; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/mysqld.service.d
           mqoverride.conf
   Active: active (running) since Thu 2020-07-16 19:49:10 JST; 7h ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 40 (limit: 4915)
   CGroup: /system.slice/mysqld.service
           tq642 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/usr/local/mysql/data --pid-file=/usr/local/mysql/data/raspberrypi402.pid
           mq728 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/var/log/mysqld.log --pid-file=/usr/local/mysql/data/raspberrypi402.

 7月 16 19:48:58 raspberrypi402 systemd[1]: Starting LSB: start and stop MySQL...
 7月 16 19:48:59 raspberrypi402 mysqld[630]: Starting MySQL
 7月 16 19:49:10 raspberrypi402 mysqld[630]: ............
 7月 16 19:49:10 raspberrypi402 systemd[1]: Started LSB: start and stop MySQL.

 $ mysql -u root -p
 Enter password:[MySQLのrootの新しいパスワード]
 Welcome to the MySQL monitor.  Commands end with ; or \g.
 Your MySQL connection id is 9
 Server version: 8.0.20 Source distribution

 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>

自動起動も出来ているし、MySQLのrootで接続することも出来ました。

9.まとめ

3年越しで、ラズパイ上でのMySQLのコンパイルに成功しました。

まだ、SQLをガシガシ流していないので、正常に稼働しているかは分からないけれども。

そして、苦労したMySQL8.0.20のインストールが成功した矢先に新しいバージョン8.0.21が出ている、という現実に泣きそうだけれども。

今はこの感動の余韻に浸っていたい。


あと、7/6に発売になったMySQL徹底入門 第4版。自分はKindle版を購入しました。

実はこれが発売になると知って、ラズパイ上でもう1回MySQLをコンパイルしてみるか!となったのでした。

これ読んでDBの世界、いやMySQLの世界を改めて勉強してみようと思いました。


今日は以上!


【今日の音楽】
あの夢をなぞって
YOASOBI
2020-01-18