PHP
MySQL
Bluemix

Bluemix CFランタイムのPHP と DBaaS MySQLを繋いでアプリを動かしてみた

Bluemix で PHP アプリを実行するための記事の3回目で、PHPが動作するCFコンテナ(ランタイム)から MySQLサーバーへ接続して、PHPアプリを動作させる方法についてもメモです。

今回実現したいこと

これまで、PHP開発環境の整備、Bluemix上でのPHP実行環境について、調べて整理してきました。
* PHPの開発環境を作るためのリンク集と実施例
* Bluemix CFコンテナでPHPの掲示板を動作させたメモ

今回は、さらに一歩進めて、次図の様に、PHP Buildpackで実行するCFランタイム(コンテナ)とMySQLマネージドサービスと接続したいと思います。

スクリーンショット 2017-07-20 11.08.57.png

MySQLについて

IT業界で、MySQLを知らない人は居ないと思うのですが、自分の理解を確かめるために、書いておきます。

MySQL は、もっとも普及しているオープンソース SQL データベース管理システムです。もともと、スウェーデンの単一の営利企業である「MySQL AB」によってメンテナンスされていました。2008年2月26日に MySQL AB がサン・マイクロシステムズに買収されたことをもって、サン・マイクロシステムズの所有となり、その後、2010年1月27日、サン・マイクロシステムズがオラクルに買収されたことにより、商標権ならびに著作権もオラクルに移管されました。現在は、オラクル社により開発、流通、およびサポートが行われています。(1),(2)

Bluemixで利用できる MySQLマネージドサービス

Bluemix で利用できる MySQLマネージドサービスは、次の2種類あります。

Compose for MySQL について

参考資料(5)によれば、Compose社のMySQLデータベースのマネージドサービスは、以下を提供するとなっています。 個人的な感想としても、これは、とても良いと思います。

耐久性
Compose上のすべての MySQLは、高い可用性を実現するため 3ノードクラスタ構成で、HAproxyをプロキシとして使用し、SSLサポートを提供します。MySQLのクラスタは、別々のゾーンの別々のマシン上に、リーダーとフォロワーメンバーが、構成されています。

バックアップ
自動化されたバックアップは毎日行われ7日間保持に加え、 4回の週次バックアップ、3回の月次バックアップがあります。バックアップのオンデマンド・オプションにより、週に最大10回のバックアップが可能です。バックアップは追加費用は無しで、APIを使用して作成および取得することもできます。

オートスケーリング
ストレージの使用量が増えるにつれて、Composeプラットフォームは自動的に1:10の RAM 対 ストレージの比率を維持し、データベースは常にパフォーマンスが向上します。 ユーザーは、特別なワークロードやイベントのためのComposeコンソールを使用してスケーリングを手動で制御することもできます。

管理
すべてのComposeデータベースのサービスは、日々のログとリアルタイムのメモリ使用量のメトリックが、コンソールから提供されます。

接続 受入れ
SSLはデフォルトで有効になっているため、ユーザーはアプリケーションを作成UIに表示されているURLに接続するだけです。 MySQL用のComposeは、SSL以外の接続も受け付けます。 HAプロキシでは、IPホワイトリストを使用して、どのクライアントがデータベースに接続できるかをさらに制限できます。

接続 出力
データベースサービスからの発信接続には、ログをLoggly、Papertrailおよびその他のサービスにリアルタイムでエクスポートするためのSyslog-NGアドオンが含まれます。

ClearDB Managed MySQL について

参考資料(7)によれば、20万のユーザーをサポートするデータベース・サービスで、Azure, AWS, Google, Bluemix でサービスを展開するとなっています。

  • 高可用性、低いレイテンシのMySQLデータベースのサービスを提供
  • 定期バックアップ 複数リージョン、複数タイムゾーンで、データベースのバックアップを提供、バックアップ管理ツールを使って、即時バックアップ、リストアができます。
  • データベースのデータとバックアップのデータも、共に暗号化されています。SSL証明書を使って暗号通信で接続されます。
  • 24時間、7日間、監視していますから、いつでも使え、安全です。
  • 我が社のグラフィカルツールは、パフォーマンス分析を簡単にします。
  • APIによって、リアルタイム監視、バックアップをおこなえます。

料金

この金額は、1ドル = 110円で計算し、端数を切り上げた目安です。 利用にあたっては、それぞれのホームページで確認してください。

Compose for MySQL

  • ストレージ 1GB、RAM 100MB ¥3千円/月
  • ストレージ 10GB、RAM 1GB ¥2万1千円/月
  • ストレージ 100GB, RAM 10GB ¥20万円/月

データ量に応じたオートスケールで、請求額が変動します。

ClearDB

  • ストレージ 10MB 無料
  • ストレージ 25GB RAM 2GB ¥2万8千円/月 P25-S 本番用
  • ストレージ 100GB RAM 8GB ¥11万円/月 P100-S 本番用

二つを並べてみるのは、難しくComposeは3ノード構成なので、若干費用が割高で、Compose はオートスケールするのに対して、ClearDBはサイズが決まっているのでアップグレードが必要になりますね。

どっちを使うか迷いますが、今回は、Compose for MySQL を利用して進めたいと思います。

コマンドラインから MySQLサーバーとの接続

参考資料

Compose for MySQL を作成すると、次の画面が表示されます。まずは、mysqlクライアントで、接続してみたいと思います。

スクリーンショット 2017-07-20 14.07.56.png

上記画面のコマンドライン (Comman Line)の枠の中を実行して、ComposeのMySQLサーバーへ接続します。 --ssl-modeを設定することで、クライアントとサーバーの間の通信は、暗号化されます。

mysql -u admin -p --host sl-us-south-1-portal.3.dblayer.com --port 17695 --ssl-mode=REQUIRED

スクリーンショット 2017-07-20 14.50.00.png

本当に暗号化されているか? 

ちょっと笑われそうですが、本当に暗号化が聞いているか、気になりませんか? 僕は「暗号化しています」と言われて、はい、そうですか、と飲み込めない理系人間なので、ちょっと確認です。

スクリーンショット 2017-07-20 16.18.49.png

次のコマンドを実行した場合に、暗号を有効にしているケースと、そうでないケースのパケットのダンプして、見比べてみます。

スクリーンショット 2017-07-20 14.53.35.png

--ssl-mode=DISABLE 平文の場合
右側のASCIIで表示している部分を見れば、上記のコマンドと結果を読み取れますね。 つまり、このケースは、インターネットを平文で流れていることになります。
スクリーンショット 2017-07-20 14.53.22.png

--ssl-mode=REQUIRED 暗号文の場合
こちらのケースでは、ACSII文字で、全く読み取れませんね。 どうやら暗号化されている様です。 --ssl-mode=REQUIREDを設定しておけば、暗号化機能が有効になるという事ですね。
スクリーンショット 2017-07-20 14.54.52.png

暗号化を必須として平文での接続を禁止してくれると良いのですが、とこに、プログラムから接続するケースでは、注意が必要そうですね。

PHPコードからの接続テスト

次の開発環境である自分のラップトップ・マシンから、インターネット上のCompose MySQLへ接続しています。
PHP から MySQLサーバーへ接続する場合、接続方法に3種の方法があります(10)

  • mysqli extension (the "i" stands for improved)
  • PDO PHP Data Objects
  • mysql PHP拡張モジュール

mysqliは、MySQLのみ対応し、PDOは12種類の異なるデータベースに対応する(11)とされています。 将来、MySQL以外にもPostgreSQLやDB2に繋いでみたいので、PDOを選択することにします。

自分のラップトップ・マシンから次のコマンドを実行します。と言いたい処ですが、このコードは、MySQLのパスワードを平文でインターネットへ流してしまうので、実行するべきではないコードです。

     1  <?php
     2  $user = 'admin';
     3  $pass = '****************';
     4  $dsn = 'mysql:host=sl-us-south-1-portal.3.dblayer.com;port=17695;dbname=mysql';
     5  
     6  $dbh = new PDO($dsn, $user, $pass);
     7  foreach($dbh->query('SELECT user,password_last_changed from user') as $row) {
     8      print_r($row);
     9  }
    10  $dbh = null;
    11  
    12  ?>

次が、暗号化処理を加えたコードが次のコードですが、これを PHP5.6.30 で実行すると、エラーが発生します。

imac:compose maho$ php -v
PHP 5.6.30 (cli) (built: Jul 17 2017 22:07:06) 以下省略
     1  <?php
     2  $user = 'admin';
     3  $pass = 'GHQHRORHPDWYXHFB';
     4  $dsn = 'mysql:host=sl-us-south-1-portal.3.dblayer.com;port=17695;dbname=mysql';
     5  $ops = array(
     6      PDO::MYSQL_ATTR_SSL_CA => 'cert2.pem'
     7  );
     8  
     9  $dbh = new PDO($dsn, $user, $pass, $ops);
    10  foreach($dbh->query('SELECT user,password_last_changed from user') as $row) {
    11      print_r($row);
    12  }
    13  $dbh = null;
    14  ?>

エラ−は以下の内容で、証明書のCNが期待と異なるという内容です。 これでは、さすがにこれ以上手が出せません。この様なエラーとなる原因は、HAProxyと、その背後にいるMySQLサーバーとでは、CNが異なっているためと考えられます。

imac:compose maho$ php test2.php
PHP Warning:  PDO::__construct(): Peer certificate CN=`bmix-dal-yp-b76e6b0e-d5c3-4926-9d8c-d804c365b2fd' did not match expected CN=`sl-us-south-1-portal.3.dblayer.com' in /Users/maho/compose/test2.php on line 9

PHPの問題判別と対策

Compose のサポートにメールを出すと共に、PHPのバグを調べてみます。 5.6系と7系であたってみます。それらしいのが有りますね。

スクリーンショット 2017-07-20 20.22.30.png

スクリーンショット 2017-07-20 20.23.58.png

この中に、エラーメッセージが全く同じバグ・レポートが発見できました。 https://bugs.php.net/bug.php?id=71845 phpのバージョンが7.0.4 になっていますが、問題の本質は同じの様です。

スクリーンショット 2017-07-20 20.03.09.png

バグレポートは、Closeになっていませんが、最後まで読むと、Pull Request が提出され、7.0.8に適用されていて、PHP 7.0.18で動作しているとの書き込みがあります。
add a attribute to specify CN in PDO(version 7) #1913 https://github.com/php/php-src/pull/1913

phpenv を使って、PHP7系の最新版に切り替えてテストします。

imac:compose maho$ phpenv local 7.1.7
7.1.7
imac:compose maho$ php -v
PHP 7.1.7 (cli) (built: Jul 20 2017 19:04:25) ( NTS )

次の通り、Pull Request #1913 で追加された設定を7行目に追加します。 追加された設定の意味は、MySQLサーバーの証明書と比較しない様にする設定です。

     1  <?php
     2  $user = 'admin';
     3  $pass = '****************';
     4  $dsn = 'mysql:host=sl-us-south-1-portal.3.dblayer.com;port=17695;dbname=mysql';
     5  $ops = array(
     6      PDO::MYSQL_ATTR_SSL_CA => 'cert2.pem',
     7      PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false  // <<--- 追加
     8  );
     9  $dbh = new PDO($dsn, $user, $pass, $ops);
    10  foreach($dbh->query('SELECT user,password_last_changed from user') as $row) {
    11      print_r($row);
    12  }
    13  $dbh = null;
    14  ?>

それでは、テストしてみます。 SSL通信が確立され、SELECTの結果を得ることができました。 良かった良かった。

imac:compose maho$ php ./test2fix.php 
Array
(
    [user] => root
    [0] => root
    [password_last_changed] => 2017-06-29 23:49:53
    [1] => 2017-06-29 23:49:53
)
Array
(
    [user] => mysql.sys
    [0] => mysql.sys
    [password_last_changed] => 2017-06-29 23:49:53
    [1] => 2017-06-29 23:49:53
)
<以下省略>

ということで、Compose for MySQL へ PHPでつなげる場合は、7.0.18以降のバージョンを利用する必要があることが解りましまた。

調べている内に、Compsoe 社のサポートからメールが返ってきました。 やはり、HAProxy の後ろにある MySQLメンバーと照合してしまう事が原因で、CAだけを照合するモードに切り替える事が解決するという事です。コマンドラインから実行する時も注意が必要ですね。

Hi Maho,

this is a known issue with no estimate of when a fix will be available. I.e the following will fail:

mysql -u admin -p --host <host> --port <port> --ssl-mode=REQUIRED --ssl-mode=VERIFY_IDENTITY --ssl-ca=mysql.crt

The reason for the failure is that for MySQL we pass the SSL connection through the HAProxy and terminate on the MySQL member. Our certificate generation process only includes the host of the capsule where SSL terminates in the AltNames. Therefore for MySQL it doesn't get the hostname of the HAProxy/portal. We have the exact same issue on our Postgresql deployments as well.

In the meantime you'll have to use unverified connections or just verify the CA. I.e. this does work:

mysql -u admin -p --host <host> --port <port> --ssl-mode=REQUIRED --ssl-mode=VERIFY_CA --ssl-ca=mysql.crt

これで原因と対策は、明確になった訳ですが、次にデプロイする際に、PHPのバージョンを7.0.18以降にする必要があります。

PHPビルドパックへのPHPのバージョン指定

bx cf push する前に .bp-config を作ります。

$ ls -al
total 0
drwxr-xr-x   4 maho  staff   136  7 20 21:07 .
drwxr-xr-x  36 maho  staff  1224  7 19 23:37 ..
drwxr-xr-x   3 maho  staff   102  7 20 21:02 .bp-config
drwxr-xr-x@  6 maho  staff   204  4 15  2015 htdocs

それから options.json のファイルを作成して、下記の様に記述します。 これで PHP7.1系の最新バージョンが

imac:unko maho$ cd .bp-config/
imac:.bp-config maho$ cat options.json 
{
    "PHP_VERSION": "{PHP_71_LATEST}"
}

この設定が可能かどうかは、ビルドパックの次のファイルを確認する必要があります。 https://github.com/cloudfoundry/php-buildpack/blob/master/defaults/options.json

CFランタイム環境の環境変数取得

Bluemix のランタイム環境や、開発用ラップトップ・マシンで、サービス資格情報を取得するためのPHPコードをBluemixサンプルコード(13) や Composeのサンプルコード(14)を探してみたが、適当なサンプルが無いので、以下にサンプルコードを書きました。

main.php は、前述のサンプルコードと同じで、SSLでMySQLサーバーに接続して簡単なクエリーを実行するものです。 この中で、3行目で、vcap.phpを取り込んでいます。 そのあと、new Vcap() でインスタンス化して、JSONファイル、または、環境変数から必要な情報を取得して、バインドされたサービスへ接続できる様になります。

たぶん初めてPHPで、こんな真面目なコード書いたので、不適切な内容があったら、指摘いただけると幸いです。

index.php
     1  <!DOCTYPE html>
     2  
     3  <head>
     4  <meta charset="UTF-8">
     5  <title>SQL検索結果</title>
     6  </head>
     7  
     8  <body>
     9  <h1>SQL検索結果</h1>
    10  
    11  <?php
    12  include "vcap.php";
    13  $vcap = new Vcap('compose-for-mysql');
    14  $dsn = 'mysql:host='.$vcap->host.";port=".$vcap->port.";dbname=mysql";
    15  $ops = array(
    16      PDO::MYSQL_ATTR_SSL_CA => __DIR__ ."/". $vcap->ca_pem_filename,
    17      PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false
    18  );
    19  $dbh = new PDO($dsn, $vcap->user, $vcap->pass, $ops);
    20  foreach($dbh->query('SELECT user,password_last_changed from user') as $row) {
    21      print_r($row);
    22      print "<br>";
    23  }
    24  $dbh = null;
    25  ?>
    26  
    27  </body>
    28  </html>  

環境変数、または、vcap-local.json からサービス資格情報を読み込むクラスです。

vcap.php
     1  <?php
     2  
     3  Class Vcap
     4  {
     5      public $user;
     6      public $pass;
     7      public $host;
     8      public $port;
     9      public $ca;
    10      public $ca_pem_filename = '_compose.pem';
    11  
    12      function __construct($svc) {
    13          
    14          if (isset($_ENV["VCAP_SERVICES"])) {
    15              $vcap_services = json_decode($_ENV["VCAP_SERVICES"]);
    16          } else {
    17              $vcap_services = json_decode(file_get_contents("vcap-local.json"))->{'VCAP_SERVICES'};
    18          }
    19          
    20          $vcap = $vcap_services->{$svc}[0]->credentials;
    21          $uri = $vcap->uri; 
    22          $s1 = preg_replace('/mysql:\/\//',null,$uri);
    23          $sa = preg_split('/:/',$s1);
    24          $this->user = $sa[0];
    25          $this->pass = preg_split('/@/',$sa[1])[0];
    26          $this->host = preg_split('/@/',$sa[1])[1];
    27          $this->port = preg_split('/\//',$sa[2])[0];
    28          $this->ca = base64_decode($vcap->ca_certificate_base64);
    29          file_put_contents($this->ca_pem_filename,$this->ca);
    30      }
    31  }                        
    32  
    33  ?>

vcap-local.json のサンプルも以下に載せておきます。 これまでと同じです。 Bluemixポータル画面のサービス資格情報、または、bx cf env app名 で取得できる情報から、コピペで このファイルの中身を作成します。それと、このデータは適当に壊してあるので、使えません。

vcap-local.json
{
 "VCAP_SERVICES": {
  "compose-for-mysql": [
   {
    "credentials": {
     "ca_certificate_base64": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlekNDQW1PZ0F3SUJBZ0lFV1ZXU0V6QU5CZ2txaGtpRzl3MEJBUTBGQURBL01UMHdPd1lEVlFRREREUjAKYTNJNU9UVTFRSGxoYUc5dkxtTnZMbXB3TFdRMU5UUm1aVGMwWkRrd01qTTBNbVU0WWpZd016UXpNREUxTkdZdwpaR1ZqTUI0WERURTNNRFl5T1RJek5Ea3pPVm9YRFRNM01EWXlPVEl6TURBd01Gb3dQekU5TURzR0ExVUVBd3cwCmRHdHlPVGsxTlVCNVlXaHZieTVqYnk1cWNDMWtOVFUwWm1VM05HUTVNREl6TkRKbE9HSTJNRE0wTXpBeE5UUm0KTUdSbFl6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU1lbm5Bd25PRnpzeXNFbwpPYTVTWEJQSTBvdFovcjluZ0ZiMjJLZEk2d2FFTXZvejZOVEl2bThGSFlQTFFQK0VJOVlVUGE4NUJZRXFFU0dVCjExUkFBUUZZUCtHY2tsdnllQjhGWDN2Y2U3RDljL3NST1lpSm9XSXVSSTVVOTlGRlY2ZURUWW02dmNFZWJUTUIKdjhVdXIrMFFRWkNXZDlINlBBTXBWRjNNMExsa0pkY3BpTW5HUlBNb3dlelgzUVRoTkZNcWJDRXlISEYwVnFpLwpqeXhyL2pKMGdWTEREeVhPT3prYlJGR0psSEpCK084WE40N2F2N21jS1NkSmJWWmlNM2EzejVudzBRZ2dIcFBiClJickE2bm1BQUNzdzFHMWdqQ2gydEtrWHI1Q1NVVk5EdDdFN2FzazhDQUU2UkljZ1RVdG0zZ2tpZjRUaGxKYVQKOERFY2ZlOENBd0VBQWFOL01IMHdIUVlEVlIwT0JCWUVGRXB6Q1B5M2V4bVRVaHR2T2s3Y3FaMkJ0a1BlTUE0RwpBMVVkRZdFQi93UUVBd0lDQkRBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFRWUlLd1lCQlFVSEF3SXdEQVlEClZSMFRCQVV3QXdFQi96QWZCZ05WSFNNRUdEQVdnQlJLY3dqOHQzc1prMUliYnpwTzNLbWRnYlpEM2pBTkJna3EKaGtpRzl3MEJBUTBGQUFPQ0FRRUFmRndYeUk3OWNqdUoyYVo5N25EM1RtZ21OTlBZanV5THY5a2tDeWhDSnZuTwozSXVJNVYrQWdUY123XlRa2VIUlhCeUphRkc3NnJTdkpIRGFrVVljeEhWRlBOeXRYVkxma1Z1c1c0Z2ZlRDI1CkVBc0g2d3paVHZrd2xFa3ZDTkdSUm5OMndSSnBJcTFpNnFURFlqVWVWZHRNekR3NElHVmtFRVlxdDBvZW9SUXcKeUgyVDN3ZDlhVno0SXNFYTM3cFIyTGN6dmxMQnRxZVFBSytRV1BqdGpWRlRSN29XL1RtSG5hRmVxZzB5VjBhTQpNL3lLV054Nk15dHJBTGRDdUpmaUZqb0szRm51UExUdFB1WURjRGpyQ1VGVGVNZVQ2QStPalFBNklCZWRCVUFuCkJRVFFJMWsxQWtNbXlva1pLUEZjaHE4YTZ1bytmeDRTMGd5UEFDUEJIUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
     "db_type": "mysql",
     "deployment_id": "5955920fff1f770015000120",
     "maps": [],
     "name": "bmix-dal-yp-b76e6b0e-d5c3-4926-9d8c-d804c365b2fd",
     "uri": "mysql://*****:************@sl-us-south-1-portal.3.dblayer.com:17695/compose",
     "uri_cli": "mysql -u admin -p --host sl-us-south-1-portal.3.dblayer.com --port 17695 --ssl-mode=REQUIRED"
    },
    "label": "compose-for-mysql",
    "name": "Compose for MySQL-9q",
    "plan": "Standard",
    "provider": null,
    "syslog_drain_url": null,
    "tags": [
     "big_data",
     "data_management",
     "ibm_created",
     "ibm_beta"
    ],
    "volume_mounts": []
   }
  ]
 }
}

アプリのデプロイ

このモジュールを動作させるためには、pdo.so, pdo_mysql.so, openssl.so などのモジュールを PHP に追加する必要があります。ビルドパックに追加するのは、面倒ですから、ビルドパックの設定をオーバーライドして追加します。

以下は、アプリのディレクトリです。 htdocs の下には、上記の index.php と vcap.php があります。 そして、.bp-config を mkdir で作ります。

drwxr-xr-x   4 maho  staff   136  7 21 15:27 .bp-config
drwxr-xr-x@ 10 maho  staff   340  7 21 15:48 htdocs

ここに、options.json を作って、前述のモジュールを .so を除いて追加します。 これで、ビルドパックの中の php.ini に設定を追加することなく、default/options.json の一部をオーバーライトできます。

imac:.bp-config maho$ cat options.json
{
    "PHP_EXTENSIONS": ["bz2", "zlib", "curl", "mcrypt", "mbstring", "pdo", "pdo_mysql", "openssl" ],
    "PHP_VERSION": "{PHP_71_LATEST}"
}

これで、以下のコマンドで、デプロイすると ブラウザアクセスすると、Compose for MySQL へ SELECT を実行した結果を返してくれます。

bx cf push -m 64M -b https://github.com/takara9/php-buildpack unko3

デプロイ後、アプリをアクセスすると、次の様に画面になります。 無骨ですが、検索結果をリストしています。
スクリーンショット 2017-07-21 16.03.38.png

まとめ、感想。。。

Webやゲーム業界で、最も利用されている PHP と MySQL なので、検索したら資料がザクザク出てきて、簡単に出来ると思っていたのですが、ノウハウ資料は無いし、バグに当たるし、大変でした。 Bluemix という PaaS基盤は、こういった業界の基盤として、歓迎されると思うのですが、もっと、地均しが必要でね。

さすがに、開発者人口の多い PHP は、バグ管理の仕組みや修正の記録が公開されていて、開発者がとても多く、人気があることが良く解りました。

参考資料

(1) ウィキペディア MySQL https://ja.wikipedia.org/wiki/MySQL
(2) MySQL 5.6 リファレンスマニュアル MySQLとは https://dev.mysql.com/doc/refman/5.6/ja/what-is-mysql.html

(3) Bluemix で使えるComposeとはなんですか? について調べてみた http://qiita.com/MahoTakara/items/a614df96059d3d8749a1
(4) IBM Compose Home page https://www.compose.com
(5) Hosted MySQL Beta https://www.compose.com/databases/mysql
(6) ClearDB Home page http://w2.cleardb.net/
(7) ClearDB Why ClearDB? http://w2.cleardb.net/why-cleardb/
(8) IBM Bluemix Catalog Compose MySQL https://console.bluemix.net/catalog/services/compose-for-mysql?env_id=ibm:yp:us-south&taxonomyNavigation=apps
(9) IBM Bluemix Catalog ClearDB Managed MySQL Database https://console.bluemix.net/catalog/services/cleardb-managed-mysql-database?env_id=ibm:yp:us-south&taxonomyNavigation=apps
(10) PHP Documentation MySQL 用 PHP ドライバの概要 どの API を使うか http://php.net/manual/ja/mysqlinfo.api.choosing.php
(11) w3schools.com PHP Connect to MySQL https://www.w3schools.com/php/php_mysql_connect.asp
(12) PHP Documentation MySQLi mysqli::real_connect http://php.net/manual/en/mysqli.real-connect.php
(13) GitHub IBM Bluemix https://github.com/IBM-Bluemix?utf8=%E2%9C%93&q=php&type=&language=
(14) GitHub Compose https://github.com/compose
(15) PHP Documentation MySQL ドライバおよびプラグイン http://php.net/manual/ja/set.mysqlinfo.php
(16) PHP【保存版!!】PHPからMySQLに接続する方法etc【データベース】 http://qiita.com/icelandnono/items/0ae83baa779c293897a5
(17) ポンクソフト PHPでMySQLを使う - PHP入門 http://ponk.jp/php/basic/php_mysql