PHP 5のサポートが終了したにもかかわらず、PHP 5の上に構築されたレガシーアプリケーションがあり、本番環境またはテスト環境で実行する必要があります。オペレーティングシステムリポジトリを介してPHPパッケージをインストールしている場合でも、PHP5パッケージになってしまう可能性があります。 CentOS7オペレーティングシステム。そうは言っても、レガシーアプリケーションを新しいバージョンのデータベースで実行し、新しい機能を利用する方法は常にあります。
このブログ投稿では、CentOS7オペレーティングシステム上で最新バージョンのMySQL8.0を使用してPHP5アプリケーションを実行する方法について説明します。このブログは、新しい環境で新しいMySQL8.0と一緒にPHP5アプリケーションを実行する必要がある内部プロジェクトの実際の経験に基づいています。新しいバージョンで導入された重要な改善点をすべて活用するには、MySQL8.0と一緒に最新バージョンのPHP7を実行するのが最適であることに注意してください。
CentOS7上のPHPとMySQL
まず、php-mysqlパッケージによって提供されているファイルを見てみましょう:
$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
$ repoquery -q -l --plugins php-mysql
/etc/php.d/mysql.ini
/etc/php.d/mysqli.ini
/etc/php.d/pdo_mysql.ini
/usr/lib64/php/modules/mysql.so
/usr/lib64/php/modules/mysqli.so
/usr/lib64/php/modules/pdo_mysql.so
デフォルトでは、標準のLAMPスタックコンポーネントがCentOS 7に付属している場合、たとえば次のようになります。
$ yum install -y httpd php php-mysql php-gd php-curl mod_ssl
次の関連パッケージがインストールされます:
$ rpm -qa | egrep 'php-mysql|mysql|maria'
php-mysql-5.4.16-46.el7.x86_64
mariadb-5.5.60-1.el7_5.x86_64
mariadb-libs-5.5.60-1.el7_5.x86_64
mariadb-server-5.5.60-1.el7_5.x86_64
次に、次のMySQL関連モジュールがPHPにロードされます。
$ php -m | grep mysql
mysql
mysqli
pdo_mysql
MySQL関連クライアントのphpinfo()によって報告されたAPIバージョンを見ると、それらはすべて、インストールしたMariaDBバージョンと一致しています。
$ php -i | egrep -i 'client.*version'
Client API version => 5.5.60-MariaDB
Client API library version => 5.5.60-MariaDB
Client API header version => 5.5.60-MariaDB
Client API version => 5.5.60-MariaDB
この時点で、インストールされたphp-mysqlモジュールがビルドされ、MariaDB5.5.60と互換性があると結論付けることができます。
MySQL8.0のインストール
ただし、このプロジェクトでは、MySQL 8.0で実行する必要があるため、Percona Server 8.0を選択して、そのサーバーにあるデフォルトの既存のMariaDBインストールを置き換えました。そのためには、Perconaリポジトリをインストールし、PerconaServer8.0リポジトリを有効にする必要があります。
$ yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
$ percona-release setup ps80
$ yum install percona-server-server
ただし、最後のコマンドを実行した後、次のエラーが発生しました。
--> Finished Dependency Resolution
Error: Package: 1:mariadb-5.5.60-1.el7_5.x86_64 (@base)
Requires: mariadb-libs(x86-64) = 1:5.5.60-1.el7_5
Removing: 1:mariadb-libs-5.5.60-1.el7_5.x86_64 (@anaconda)
mariadb-libs(x86-64) = 1:5.5.60-1.el7_5
Obsoleted By: percona-server-shared-compat-8.0.15-6.1.el7.x86_64 (ps-80-release-x86_64)
Not found
Error: Package: 1:mariadb-server-5.5.60-1.el7_5.x86_64 (@base)
Requires: mariadb-libs(x86-64) = 1:5.5.60-1.el7_5
Removing: 1:mariadb-libs-5.5.60-1.el7_5.x86_64 (@anaconda)
mariadb-libs(x86-64) = 1:5.5.60-1.el7_5
Obsoleted By: percona-server-shared-compat-8.0.15-6.1.el7.x86_64 (ps-80-release-x86_64)
Not found
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest
上記は単に、Percona Server共有compatパッケージが、すでにインストールされているmariadb-serverパッケージに必要なmariadb-libs-5.5.60を廃止することを意味します。これはまったく新しいサーバーであるため、既存のMariaDBパッケージを削除することは大きな問題ではありません。最初にそれらを削除してから、もう一度PerconaServer8.0をインストールしてみましょう。
$ yum remove mariadb mariadb-libs
...
Resolving Dependencies
--> Running transaction check
---> Package mariadb-libs.x86_64 1:5.5.60-1.el7_5 will be erased
--> Processing Dependency: libmysqlclient.so.18()(64bit) for package: perl-DBD-MySQL-4.023-6.el7.x86_64
--> Processing Dependency: libmysqlclient.so.18()(64bit) for package: 2:postfix-2.10.1-7.el7.x86_64
--> Processing Dependency: libmysqlclient.so.18()(64bit) for package: php-mysql-5.4.16-46.el7.x86_64
--> Processing Dependency: libmysqlclient.so.18(libmysqlclient_18)(64bit) for package: perl-DBD-MySQL-4.023-6.el7.x86_64
--> Processing Dependency: libmysqlclient.so.18(libmysqlclient_18)(64bit) for package: 2:postfix-2.10.1-7.el7.x86_64
--> Processing Dependency: libmysqlclient.so.18(libmysqlclient_18)(64bit) for package: php-mysql-5.4.16-46.el7.x86_64
--> Processing Dependency: mariadb-libs(x86-64) = 1:5.5.60-1.el7_5 for package: 1:mariadb-5.5.60-1.el7_5.x86_64
---> Package mariadb-server.x86_64 1:5.5.60-1.el7_5 will be erased
--> Running transaction check
---> Package mariadb.x86_64 1:5.5.60-1.el7_5 will be erased
---> Package perl-DBD-MySQL.x86_64 0:4.023-6.el7 will be erased
---> Package php-mysql.x86_64 0:5.4.16-46.el7 will be erased
---> Package postfix.x86_64 2:2.10.1-7.el7 will be erased
mariadb-libsを削除すると、これに依存する他のパッケージもシステムから削除されます。私たちの主な関心事は、mariadb-libsによって提供されるlibmysqlclient.so.18への依存のために削除されるphp-mysqlパッケージです。後で修正します。
その後、エラーなしでPerconaServer8.0をインストールできるようになります。
$ yum install percona-server-server
この時点で、サーバーにあるMySQL関連のパッケージは次のとおりです。
$ rpm -qa | egrep 'php-mysql|mysql|maria|percona'
percona-server-client-8.0.15-6.1.el7.x86_64
percona-server-shared-8.0.15-6.1.el7.x86_64
percona-server-server-8.0.15-6.1.el7.x86_64
percona-release-1.0-11.noarch
percona-server-shared-compat-8.0.15-6.1.el7.x86_64
PHPアプリケーションを新しくインストールしたPerconaServer8.0サーバーに接続するためのモジュールを提供するphp-mysqlパッケージがないことに注意してください。ロードされたPHPモジュールをチェックすることでこれを確認できます。次のコマンドで空の出力を取得する必要があります:
$ php -m | grep mysql
もう一度インストールしましょう:
$ yum install php-mysql
$ systemctl restart httpd
今、私たちはそれらを持っており、PHPにロードされています:
$ php -m | grep mysql
mysql
mysqli
pdo_mysql
また、コマンドラインからPHP情報を確認することで確認できます:
$ php -i | egrep -i 'client.*version'
Client API version => 5.6.28-76.1
Client API library version => 5.6.28-76.1
Client API header version => 5.5.60-MariaDB
Client API version => 5.6.28-76.1
クライアントAPIライブラリバージョンとAPIヘッダーバージョンの違いに注意してください。後のテストで後遺症が見られます。
MySQL 8.0サーバーを起動して、PHP5アプリケーションをテストしてみましょう。 MariaDBに/var/ lib / mysqlのdatadirを使用させたので、最初にそれを消去し、datadirを再初期化し、適切な所有権を割り当てて起動する必要があります:
$ rm -Rf /var/lib/mysql
$ mysqld --initialize
$ chown -Rf mysql:mysql /var/lib/mysql
$ systemctl start mysql
Perconaサーバーによって生成された一時的なMySQLルートパスワードをMySQLエラーログファイルから取得します。
$ grep root /var/log/mysqld.log
2019-07-22T06:54:39.250241Z 5 [Note] [MY-010454] [Server] A temporary password is generated for [email protected]: 1wAXsGrISh-D
これを使用して、user [email protected]の初回ログイン時にログインします。サーバーでさらにアクションを実行する前に、一時パスワードを別のパスワードに変更する必要があります。
$ mysql -uroot -p
mysql> ALTER USER [email protected] IDENTIFIED BY 'myP455w0rD##';
次に、アプリケーションに必要なデータベースリソースの作成に進みます。
mysql> CREATE SCHEMA testdb;
mysql> CREATE USER [email protected] IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON testdb.* TO [email protected];
完了したら、既存のデータをバックアップからデータベースにインポートするか、データベースオブジェクトを手動で作成します。これで、データベースをアプリケーションで使用できるようになりました。
エラーと警告
このアプリケーションでは、アプリケーションがソケット経由で接続できることを確認するための簡単なテストファイルがあります。つまり、ポート3306のローカルホストを使用して、ネットワーク経由のすべてのデータベース接続を排除します。すぐに、バージョンの不一致の警告が表示されます:
$ php -e test_mysql.php
PHP Warning: mysqli::mysqli(): Headers and client library minor version mismatch. Headers:50560 Library:50628 in /root/test_mysql.php on line 9
同時に、php-mysqlモジュールで認証エラーが発生することもあります:
$ php -e test_mysql.php
PHP Warning: mysqli::mysqli(): (HY000/2059): Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory in /root/test_mysql.php on line 9
または、MySQLネイティブドライバーライブラリ(php-mysqlnd)を使用して実行している場合、次のエラーが発生します。
$ php -e test_mysql.php
PHP Warning: mysqli::mysqli(): The server requested authentication method unknown to the client [caching_sha2_password] in /root/test_mysql.php on line 9
さらに、文字セットに関して別の問題が発生する可能性があります:
PHP Warning: mysqli::mysqli(): Server sent charset (255) unknown to the client. Please, report to the developers in /root/test_mysql.php on line 9
解決策と回避策
認証プラグイン
PHP5のphp-mysqlndライブラリもphp-mysqlライブラリも、MySQL8.0の新しい認証方法をサポートしていません。 MySQL 8.0.4以降、認証方法が「caching_sha2_password」に変更されました。これは、以前のバージョンでデフォルトであった「mysql_native_password」と比較した場合に、より安全なパスワードハッシュを提供します。
MySQL8.0での下位互換性を可能にするため。 MySQL構成ファイル内で、[mysqld]セクションの下に次の行を追加します。
default-authentication-plugin=mysql_native_password
MySQLサーバーを再起動すると、問題がないはずです。上記の変更の前に、たとえばバックアップと復元を介してデータベースユーザーが作成されている場合は、DROPUSERステートメントとCREATEUSERステートメントを使用してユーザーを再作成します。 MySQLは、新しいユーザーを作成するときに、新しいデフォルトの認証プラグインに従います。
マイナーバージョンの不一致
php-mysqlパッケージでは、インストールされているライブラリのバージョンを確認すると、違いに気付くでしょう:
$ php -i | egrep -i 'client.*version'
Client API version => 5.6.28-76.1
Client API library version => 5.6.28-76.1
Client API header version => 5.5.60-MariaDB
Client API version => 5.6.28-76.1
PHPライブラリはMariaDB5.5.60libmysqlclientでコンパイルされ、クライアントAPIバージョンはバージョン5.6.28で、percona-server-shared-compatパッケージによって提供されます。警告にもかかわらず、サーバーから正しい応答を得ることができます。
ライブラリバージョンの不一致に関するこの警告を抑制するには、MySQLクライアントサーバーライブラリ(libmysqlclient)に依存しないphp-mysqlndパッケージを使用します。 MySQLのドキュメントに記載されているように、これが推奨される方法です。
php-mysqlライブラリをphp-mysqlndに置き換えるには、次のコマンドを実行します。
$ yum remove php-mysql
$ yum install php-mysqlnd
$ systemctl restart httpd
php-mysqlを置き換えることができない場合、最後の手段は、PHPをMySQL 8.0クライアントサーバーライブラリ(libmysqlclient)で手動でコンパイルし、コンパイルしたライブラリファイルを/ usr / lib64 / php / modules /ディレクトリにコピーして、古いmysqliを置き換えることです。つまり、mysql.soとpdo_mysql.soです。これは、成功率の可能性が低い少し面倒です。これは主に、現在のMySQLバージョンのヘッダーファイルの非推奨の依存関係が原因です。これを回避するには、プログラミングの知識が必要です。
互換性のない文字セット
MySQL 8.0.1以降、MySQLはデフォルトの文字セットをlatin1からutf8mb4に変更しました。 utf8mb4文字セットは、現在データベースに言語文字だけでなく、記号、新しく導入された絵文字なども格納する必要があるため、便利です。 Charset utf8mb4は、1文字あたり1〜3バイトを使用する標準のutf8(別名utf8mb3)と比較した場合、1文字あたり1〜4バイトを使用するUnicode文字セットのUTF-8エンコーディングです。
多くのレガシーアプリケーションは、utf8mb4文字セットの上に構築されていませんでした。したがって、MySQLサーバーの文字設定を従来のPHPドライバーで理解できるものに変更するとよいでしょう。 [mysqld]セクションのMySQL構成に次の2行を追加します。
collation-server = utf8_unicode_ci
character-set-server = utf8
オプションで、次の行をMySQL構成ファイルに追加して、utf8を使用するためのすべてのクライアントアクセスを合理化することもできます。
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
変更を有効にするには、MySQLサーバーを再起動することを忘れないでください。この時点で、アプリケーションはMySQL8.0に対応しているはずです。
今のところ以上です。レガシーアプリケーションをMySQL8.0に移行する際に他に問題がある場合は、コメントセクションでフィードバックを共有してください。