XAMPP環境で MySQL 5.7 を動かす

　MySQLのJSON型を使って開発をしたい。しかも、XAMPP環境で…！

　──Vagrant + VirtualBox 使えばええやん。

　確かにその通りだ。その通りなのだが、私の非力なノートPC（メモリ4GBのWindows8.1マシン）では、仮想環境建てると重くて逆に開発しづらいのだ。その点、非力なマシンでもXAMPPはサクサク動く。しかし…ひとつ問題があった。XAMPPの最新パッケージではDBがMariaDBになっていることだ。XAMPPに同梱されているMariaDBでは、JSON型がサポートされていないじゃないの！

　そんなこんなで、最新版のXAMPP環境でMySQL5.7を動かすまでをやってみた。

## XAMPPのバージョン確認

　まず、現在のXAMPPのバージョンを確認しよう。コマンドプロンプト（PowerShell等）から、

```bash
> cat xampp/readme_en.txt |grep "XAMPP Version"
###### ApacheFriends XAMPP Version 5.6.8 ######
```

　──とするか、もしくは、XAMPPのインストールフォルダ内の `readme_en.txt` を直接開いて確認するのが手っ取り早いかも。

　私のXAMPP環境バージョン 5.6.8 では、 MySQL 5.5.32 がインストールされていた。

　現時点（2017/5/31時点）でXAMPPの5系（PHP 5.x系）最新バージョンは **5.6.30** となっている。なお、このパッケージやPHP7系版では、DBがMariaDBに変わっている。冒頭でも書いたが、MariaDBはMySQL互換なのだが、MySQL 5.7から拡張されたJSON型のカラムには対応していない。ただ、互換性のある機能として「**Dynamic Columns**」というblob型の拡張が施されていて、JSON形式のデータをやり取りすることはできる。
　でもねぇ……自分的に、blob型でJSONをやり取りするのにはちょっと違和感がある。やはりここは、MySQL 5.7で純正なJSON型カラムを操作できる環境を構築する道を貫くことにする。

## XAMPPのアップグレード

　とりあえず、XAMPPのアップグレードをする。といっても、XAMPPはGUI内などからアップグレードとかできないので、アンインストール <i class="fa fa-long-arrow-right"></i> 再インストールという手順を踏む必要があるのだ。

### 移行データのバックアップ

　最初の手順としては、新バージョンに移行する設定ファイル等のデータをバックアップすることだ。

**1.  Apache系の設定ファイルのバックアップ**

* htpd.conf ( `xampp/apache/conf/htpd.conf` )
* htpd-vhosts.conf ( `xampp/apache/conf/extra/htpd-vhosts.conf` )

**2. MySQLの全データのバックアップ**

* mysql/data ( `xampp/mysql/data` )

> ここで、 phpMyAdmin で全データベースをエクスポートしておくとさらに安心できる。その場合、XAMPPコンソールからphpMyAdminを起動して、「エクスポート」タブを選択。エクスポート方法:詳細から全データベースを選択して、生成オプションを全部チェックした後に「実行」をクリックしてエクスポートしておこう。
　これで、もしMySQLデータファイルから新DBのデータがうまく復旧できなかった時でも、エクスポートファイルからデータの復旧が可能になる。

**3. PHPの設定ファイル**

* php.ini ( `xampp/php/php.ini` )

　他に利用しているモジュールなどがあれば、それらの設定ファイル等もバックアップしておくと良い。私の例だと、ユニットテスト用のphpunitとか（その辺は省略）。

### XAMPPのアンインストール

　もしApacheやMySQLが起動していたら、停止しておこう。

　そして、`xampp/uninstall.exe` を実行しよう。

　アンインストーラが起動すると、「Do you want to uninstall XAMPP and all of its modules?」と質問されるので、「Yes」をクリックする。次に「Remove the C:\xampp\htdocs folder too?」と訊かれるので、「No」をクリックする。
　これで、htdocsを残したままXAMPPをアンインストールできる（結構時間がかかる）。

　アンインストールが終了すると、xamppフォルダの中には、

- `htdocs/`
- `mailoutput/`
- `xampp-control.log`

　のみが残っている状態になる。
　ここで、 `xampp` フォルダの名前を `xampp.old` とかに変更しておこう。でないと、再インストールする時に怒られる。

### 最新版のXAMPPをインストール

　[Apache Friends](https://www.apachefriends.org/index.html)から最新XAMPPパッケージのインストーラをダウンロードして、実行する。

　インストーラ起動時に色々と訊かれるが、基本的に全て「Next」で進んで構わない。ちなみにインストールには、結構時間がかかる。メモリの少ないノートPCとかだと、Setupダイアログが**応答なし**とかになることもあるので、できる限りメモリを確保した状態（メモリ食い虫のブラウザーは閉じておこう。およそ300MB程度の空きメモリは確保しておかないと厳しいかもしれない）で放置しておくのが良いだろう。
　で、しばらくするとインストールが完了するはず。

　インストールが完了したら、XAMPPの各パッケージのバージョンを確認してみよう。インストールフォルダ直下の `xmapp/readme_en.txt` を開いてみる。

```text
###### ApacheFriends XAMPP Version 5.6.30 ######

Important! PHP in this package needs the Microsoft Visual C++ 2008 Redistributable package from
http://www.microsoft.com/en-us/download/details.aspx?id=5582. Please ensure that the VC++ 2008 runtime
libraries are installed on your system.    

  + Apache 2.4.25
  + MariaDB 10.1.21
  + PHP 5.6.30 (VC11 X86 32bit thread safe) + PEAR
  + phpMyAdmin 4.6.5.2
  + OpenSSL 1.0.2j
  + ADOdb 518a
  + Mercury Mail Transport System v4.63 (not included in the portable version)
  + FileZilla FTP Server 0.9.41 (not included in the portable version)
  + Webalizer 2.23-04 (not included in the portable version) 
  + Strawberry Perl 5.16.1.1 Portable
  + Tomcat 7.0.56
  + XAMPP Control Panel Version 3.2.2 by hackattack142 (Great Thanks!!))
    See: http://www.apachefriends.org/f/viewtopic.php?f=16&t=46743
  + XAMPP mailToDisk 1.0 (write emails via PHP on local disk in <xampp>\mailoutput. Activated in the php.ini as mail default.)
```

　データベースが **MariaDB 10.1.21** になっている。 

### 旧環境データの移行・適用

　ここで、一旦、MySQL 5.7の事は置いておいて、アップグレードしたXAMPP環境に旧環境データを移行してしまおう。
　
　バックアップした旧XAMPP環境のファイルを新XAMPP環境下に再配置していくのだ。その際、新XAMPP環境にあるオリジナルファイルは別名にして退避しておこう。
　例えば、新XAMPP環境の `xampp/apache/conf/httpd.conf` のファイル名を `httpd.conf.orig` 等にリネームしてから、旧XAMPP環境の `httpd.conf` をコピーする──といった手順だ。

　バックアップしたファイルを一通り新XAMPP環境下へ配置したら、XAMPPコンソールからApacheとMySQL（MariaDB）を起動してみよう。おそらく、問題なく起動できるはずだ。これで、ひとまずXAMPPのアップグレードは完了だ。


## MySQL 5.7の導入

　さて、ここからが本題だ。
　この時点でXAMPPによるMariaDB環境は不要なので、XAMPPコンソールからDBをstopしよう。
　そして、MySQL 5.7をインストールする。[MySQL公式サイトのダウンロードページ](https://dev.mysql.com/downloads/mysql/) からインストーラパッケージ「MySQL Installer for Windows」をダウンロードするのだが、インストーラは2種類あるので、「**mysql-installer-community**」の方を選ぼう。2017年6月1日現在のMySQL5.7系の最新バージョンは 5.7.18 だったので、ダウンロードするインストーラは「mysql-installer-community-5.7.18.1.msi」となる。
　ダウンロードの最終確認でログインかサインアップ（無料）を求められるが、不要なら「No thanks, just start my download.」をクリックすれば、すぐダウンロードが始まる。

　ダウンロードが終わったら、インストーラを起動して、レッツ・インストール！
　インストーラの設定については、下記のサイトが参考になるかと。

> [DBOnline : MySQL 5.7.16のインストール](https://dev.mysql.com/downloads/mysql/)

　注意しないといけないのは、MySQLを開発で使うからとセットアップタイプを「Developer Default」にすると、Python等のインストールを求められたりして路頭に迷うので、「Custom」タイプからインストールするプロダクトを選ぶこと。
　私の場合、インストールプロダクトは下記のようにした:

* MySQL Server 5.7.18 （これは必須）
* MySQL Utilities 1.6.5 （ログ管理やレプリケーション管理、インデックス検証など有効なコマンドが使えるツール群）
* MySQL Shell 1.0.9 （シェルベースでデータベースを操作できる）
* Connector/ODBC 5.3.7 （これも必須。WindowsがMySQLと接続するためのドライバ）

　本当は「MySQL Workbench（データベース管理ツール phpMyAdminより高機能）」を入れたかったんだが、インストールにはVisual C++のランタイムが必要だったので却下。まぁ、必要になったら別途インストールすればいい。

　「Type and Networking」セクションでは「**Standalone MySQL Server / Classic MySQL Replication**」を選び、Server Configuration Typeでは「**Development Machine**」のままで、ConnectivityのTCP/IPのポート番号のみ3306から変更する（私は33060にした）。これでXAMPP側のMariaDBとMySQL 5.7が共存できるようになる。 

　「Accounts and Roles」セクションではrootユーザのパスワードを設定後、必要であればMySQLユーザアカウントを追加できる。私はrootパス設定以外は不要なのでスルーした。

　「Windows Service」セクションではMySQL 5.7 をWindowsのサービスとして登録するかどうかの設定だ。登録しておくと何かと便利なので、デフォルト設定のまま「Next」で良いかと。

　「Plugins and Extensions」セクションではMySQL 5.7 で実装された **Document Store** の機能を有効化するかどうかを選べる。この機能、MySQLをnoSQL的なドキュメントデータベースとして扱えるというもので、すごく興味がある。ということで、私は有効にしておいた（何気にMySQL Shellをインストールしておいたのも、この Document Store をDev APIで取り扱うためだったりする…）。

　──これで一通りの設定が完了したので、「Apply Configuration」で「Excute」すれば、MySQLがビルドされる。あとは、インストーラの指示に従って進んでいけば、晴れてインストール完了だ。

## MySQLの初期設定

　インストールされたMySQL 5.7 のWindows上での配置を確認する。
　まず、MySQL 5.7 の実行ファイル `mysql.exe` の場所は、

`C:\Program Files\MySQL\MySQL Server 5.7\bin\mysql.exe`

　そして、MySQL 5.7 の設定ファイル `my.ini` の場所は、

`C:\ProgramData\MySQL\MySQL Server 5.7\my.ini`

　──となっているはずだ（インストール時にインストールパスを変更した場合は異なる）。もし、WindowsのサービスにMySQL 5.7 を登録している場合は、「コンピューターの管理」<i class="fa fa-long-arrow-right"></i>「サービスとアプリケーション」<i class="fa fa-long-arrow-right"></i>「サービス」から「MySQL57」のプロパティを確認することで、それぞれのパスを確認できる。

　次に、MySQL 5.7 へパスを通す。コマンドプロンプトを管理者権限で開いて、

```bash
>SETX /M PATH "%PATH%;C:\Program Files\MySQL\MySQL Server 5.7\bin"

成功: 指定した値は保存されました。
```

　これでコマンドラインからMySQL 5.7 を実行できるようになる。もし、1024文字で切り捨て～とかのエラーが出る場合は、「システム」<i class="fa fa-long-arrow-right"></i>「システムの詳細設定」<i class="fa fa-long-arrow-right"></i>「環境変数」からパスを追加すればOKだ。
　パスが通っているかどうか確認してみよう。

```bash
>where mysql
C:\xampp\mysql\bin\mysql.exe
```

　ありゃ？　ちゃうやん。そう言えば、旧XAMPP運用時にMySQLのパスをXAMPP側に通していた。こんな場合は、GUI（「システム」<i class="fa fa-long-arrow-right"></i>「システムの詳細設定」<i class="fa fa-long-arrow-right"></i>「環境変数」）からパスを編集しよう（コマンドプロンプトからSETXで消すと、値が全て消えてしまうので）。編集したらもう一度、

```
>where mysql
C:\Program Files\MySQL\MySQL Server 5.7\bin\mysql.exe
```

　よし、これでOKだ。MySQLのバージョンを確認してみる。

```bash
>mysql --version
mysql  Ver 14.14 Distrib 5.7.18, for Win64 (x86_64)
```

　続いて、MySQLに接続してみよう。接続ポートを3306から33060に変更しているので、ポート指定で接続することになる。

```bash
>mysql -u root -p -P 33060
Enter password: ********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.18-log MySQL Community Server (GPL)

Copyright (c) 2000, 2017, 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 5.7 で開発する準備が完了した。
　では、旧XAMPP環境のMySQLデータを MySQL 5.7 側に移行してみよう。

## 旧XAMPP環境のDBデータをMySQL 5.7に移行

　旧XAMPP環境のMySQLデータはDataディレクトリごとバックアップして、それを新XAMPP環境のMariaDB側に暫定的に移行していた。そのDataディレクトリをMySQL5.7側に再度移動してもよいが、面倒なので、シンボリックリンクを貼ってしまおう（もし移行後にうまく動かなかったら、シンボリックリンクを削除するだけで良いので…と思っていたが、これには落とし穴がある。詳しくは後述）。
　コマンドプロンプトを開いて、

**1. MySQL 5.7 のサービスを停止する**

```bash
>sc stop MySQL57

SERVICE_NAME: MySQL57
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 3  STOP_PENDING
                                (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x1
        WAIT_HINT          : 0x5265c00
```

**2. オリジナルのDataディレクトリを丸ごとバックアップする**

```bash
>cd "C:\ProgramData\MySQL\MySQL Server 5.7"

C:\ProgramData\MySQL\MySQL Server 5.7>move Data Data.orig
        1 個のディレクトリを移動しました。
```

**3. 旧XAMPP環境のDBデータをMySQL 5.7に移行する**

　もし、以降MariaDBを使わないのであれば、新XAMPPのMariaDB下に移行したdataディレクトリにシンボリックリンクを貼るのが簡単だ。（これを実行する前に、後述の「[おまけ](#おまけ)」を読んでほしい）

```bash
C:\ProgramData\MySQL\MySQL Server 5.7>mklink /D Data C:\xampp\mysql\data
Data <<===>> C:\xampp\mysql\data のシンボリック リンクが作成されました
```

　新XAMPP環境のMariaDBも利用するし、MySQL 5.7も使うという場合は、MariaDB下に移行したdataディレクトリをコピーしてくる。

```bash
C:\ProgramData\MySQL\MySQL Server 5.7>xcopy C:\xampp\mysql\data Data /I /E
```

　リスクの少ない、後者をしておくのが良いかと。

**4. MySQL 5.7 を起動して、移行データを確認する**

```bash
>sc start MySQL57

SERVICE_NAME: MySQL57
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x3
        WAIT_HINT          : 0x3a98
        PID                : 9792
        FLAGS              :

>mysql -u root -p -P 33060
Enter password: ********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.18-log MySQL Community Server (GPL)

Copyright (c) 2000, 2017, 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 |
| cdcol              |
| dev_demo           |
| dev_demo2          |
| mysql              |
| performance_schema |
| phpmyadmin         |
| test               |
| webauth            |
| wordpress_core     |
+--------------------+
10 rows in set (0.09 sec)
```

　データベースリストを見るかぎり、旧XAMPP環境のデータベースが全て移行できているようだ。

> もし、ここでうまくデータ移行ができないようであれば、新XAMPP環境のMariaDB側で（phpMyAdminなどを使って）DBの構造とデータを全てエクスポートしてから、MySQL側へインポートしてやれば復元できるはずだ。また、旧XAMPPのアンインストール前にDBエクスポートをしていた場合は、そのファイルをインポートしてやっても良い。

　これで、新XAMPP側で開発するアプリケーションにて、参照するDBをMySQL 5.7側へ向けてやることで、JSON型カラムを使った開発ができるようになる。


## おまけ

　上記の手順で、XAMPP+MySQL5.7という環境が実現したが、この状態でXAMPP+MariaDBというXAMPP本来の環境はどうなっているか気になった。DBの接続ポートをそれぞれで別にしていることもあって、もしかしたら、一つのデータベースについて、MySQL5.7側とMariaDB側の両方からアクセスできるというハイブリッドな環境になっていたりするのだろうか……と興味がそそられたのだ。

　結果として、**XAMPP側のMariaDBは使えなくなる**。XAMPPコンソールからMySQLがstartできなくなるのだ。
　
　まぁ、いくら互換するからと言っても、RDBMSが異なるから、当然っちゃー当然か。なので、旧DBのデータ（dataディレクトリ）はそれぞれで持とう。シンボリックリンクで横着すると、MariaDB側のデータを復旧するのにいらぬ手間がかかる（痛い目見た）。

　横着せずにそれぞれにデータ移行すれば、MySQL 5.7 と MariaDB を並列で起動できるようになる。

### P.S. 実際にMySQL 5.7のJSON型を扱ってみた

　最後に、新XAMPP環境に移管したWordPress環境から、MySQL 5.7環境に接続してみたので、紹介しておく。

　まず新XAMPP環境下のWordPressの `wp-config.php` を開いて、接続するDBホストをMySQL 5.7側に変更する。

```php
define('DB_HOST', 'localhost:33060');
```

　この状態で、WordPressサイトを表示してみると、「Table 'performance_schema.session_variables' doesn't exist」のエラーが出る。これはMySQL 5.6以降にperformance_schemaがデフォルトで有効にされたため、それ以前のバージョンからデータ移行したりすると「そんなデータベース見当たらないぜ！」と怒られるものだ。なので、`mysql_upgrade` をする必要がある。

```bash
>mysql_upgrade -u root -p -P 33060
Enter password:
Checking if update is needed.
Checking server version.
Running queries to upgrade MySQL server.
Checking system database.
mysql.columns_priv                                 OK
mysql.db                                           OK
mysql.engine_cost                                  OK
:
(以下省略)
```

　アップグレードが完了したら、MySQL 5.7 を再起動しよう。

```bash
>sc stop MySQL57
>sc start MySQL57
```

　これで、エラーが出なくなった。
　さて、せっかくなのでJSON型のカラムを持つテーブルを作成してみる。

```mysql
mysql> CREATE TABLE `json_test` (
    -> `json` json DEFAULT NULL
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
    -> ;
Query OK, 0 rows affected (0.11 sec)
```

　レコードも入れてみる。

```mysql
mysql> INSERT INTO `json_test` (`json`) VALUES ('{"Name":"test", "Age":20, "Gender":"male"}');
Query OK, 1 row affected (0.02 sec)
```

　そんで、JSONデータの検索をしてみる。

```mysql
mysql> SELECT * FROM `json_test`;
+-----------------------------------------------+
| json                                          |
+-----------------------------------------------+
| {"Age": 20, "Name": "test", "Gender": "male"} |
+-----------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT json_extract(json, '$.Name') FROM `json_test`;
+------------------------------+
| json_extract(json, '$.Name') |
+------------------------------+
| "test"                       |
+------------------------------+
1 row in set (0.00 sec)

```

　おぉ～、いいねぇ。
　
　WordPressのメタ系テーブルのValueカラムとか、JSON型に変更するとイイかも。

　近いうち、自作の「CustomDataBaseTables」プラグインもJSON型に対応させなきゃいかんなぁ……。