sql >> Base de Datos >  >> RDS >> MariaDB

Cómo ejecutar aplicaciones PHP 5 con MySQL 8.0 en CentOS 7

A pesar de que PHP 5 ha llegado al final de su vida útil, todavía hay aplicaciones heredadas construidas sobre él que deben ejecutarse en entornos de producción o prueba. Si está instalando paquetes de PHP a través del repositorio del sistema operativo, aún existe la posibilidad de que termine con paquetes de PHP 5, p. Sistema operativo CentOS 7. Habiendo dicho eso, siempre hay una manera de hacer que sus aplicaciones heredadas se ejecuten con las versiones más nuevas de la base de datos y así aprovechar las nuevas funciones.

En esta publicación de blog, lo guiaremos a través de cómo podemos ejecutar aplicaciones PHP 5 con la última versión de MySQL 8.0 en el sistema operativo CentOS 7. Este blog se basa en la experiencia real con un proyecto interno que requería que la aplicación PHP 5 se ejecutara junto con nuestro nuevo MySQL 8.0 en un nuevo entorno. Tenga en cuenta que sería mejor ejecutar la última versión de PHP 7 junto con MySQL 8.0 para aprovechar todas las mejoras significativas introducidas en las versiones más recientes.

PHP y MySQL en CentOS 7

En primer lugar, veamos qué archivos proporciona el paquete 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

Por defecto, si instalamos la pila LAMP estándar, los componentes vienen con CentOS 7, por ejemplo:

$ yum install -y httpd php php-mysql php-gd php-curl mod_ssl

Obtendrá los siguientes paquetes relacionados instalados:

$ 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

Los siguientes módulos relacionados con MySQL se cargarán en PHP:

$ php -m | grep mysql
mysql
mysqli
pdo_mysql

Al mirar la versión de API informada por phpinfo() para clientes relacionados con MySQL, todos coinciden con la versión de MariaDB que hemos instalado:

$ 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

En este punto, podemos concluir que el módulo php-mysql instalado está construido y es compatible con MariaDB 5.5.60.

Instalación de MySQL 8.0

Sin embargo, en este proyecto, debemos ejecutar MySQL 8.0, por lo que elegimos Percona Server 8.0 para reemplazar la instalación predeterminada existente de MariaDB que tenemos en ese servidor. Para hacer eso, tenemos que instalar Percona Repository y habilitar el repositorio de Percona Server 8.0:

$ yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
$ percona-release setup ps80
$ yum install percona-server-server

Sin embargo, obtuvimos el siguiente error después de ejecutar el último comando:

--> 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

Lo anterior simplemente significa que el paquete de compatibilidad compartido de Percona Server dejará obsoleto el mariadb-libs-5.5.60, que es requerido por los paquetes de mariadb-server ya instalados. Dado que este es un servidor completamente nuevo, eliminar los paquetes de MariaDB existentes no es un gran problema. Eliminémoslos primero y luego intentemos instalar Percona Server 8.0 una vez más:

$ 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

Eliminar mariadb-libs también eliminará otros paquetes que dependen de esto del sistema. Nuestra principal preocupación son los paquetes php-mysql que se eliminarán debido a la dependencia de libmysqlclient.so.18 proporcionada por mariadb-libs. Lo arreglaremos más tarde.

Después de eso, deberíamos poder instalar Percona Server 8.0 sin error:

$ yum install percona-server-server

En este punto, aquí están los paquetes relacionados con MySQL que tenemos en el servidor:

$ 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

Tenga en cuenta que no tenemos paquetes php-mysql que proporcionen módulos para conectar nuestra aplicación PHP con nuestro servidor Percona Server 8.0 recién instalado. Podemos confirmar esto comprobando el módulo PHP cargado. Debería obtener una salida vacía con el siguiente comando:

$ php -m | grep mysql

Vamos a instalarlo de nuevo:

$ yum install php-mysql
$ systemctl restart httpd

Ahora los tenemos y están cargados en PHP:

$ php -m | grep mysql
mysql
mysqli
pdo_mysql

Y también podemos confirmar eso mirando la información de PHP a través de la línea de comando:

$ 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

Observe la diferencia entre la versión de la biblioteca de la API del cliente y la versión del encabezado de la API. Veremos el efecto posterior de eso más adelante durante la prueba.

Iniciemos nuestro servidor MySQL 8.0 para probar nuestra aplicación PHP5. Ya que MariaDB usó el directorio de datos en /var/lib/mysql, primero tenemos que borrarlo, reinicializar el directorio de datos, asignar la propiedad adecuada e iniciarlo:

$ rm -Rf /var/lib/mysql
$ mysqld --initialize
$ chown -Rf mysql:mysql /var/lib/mysql
$ systemctl start mysql

Obtenga la contraseña raíz temporal de MySQL generada por Percona Server del archivo de registro de errores de 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

Úselo para iniciar sesión durante el primer inicio de sesión del usuario [email protected]. Tenemos que cambiar la contraseña temporal a otra antes de poder realizar cualquier otra acción en el servidor:

$ mysql -uroot -p
mysql> ALTER USER [email protected] IDENTIFIED BY 'myP455w0rD##';

Luego, procedemos a crear nuestra base de datos de recursos requeridos por nuestra aplicación:

mysql> CREATE SCHEMA testdb;
mysql> CREATE USER [email protected] IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON testdb.* TO [email protected];

Una vez hecho esto, importe los datos existentes desde la copia de seguridad a la base de datos o cree sus objetos de base de datos manualmente. Nuestra base de datos ya está lista para ser utilizada por nuestra aplicación.

Errores y Advertencias

En nuestra aplicación, teníamos un archivo de prueba simple para asegurarnos de que la aplicación pudiera conectarse a través de un socket o, en otras palabras, localhost en el puerto 3306 para eliminar todas las conexiones de base de datos a través de la red. Inmediatamente recibiríamos la advertencia de discrepancia de versión:

$ 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

Al mismo tiempo, también encontraría el error de autenticación con el módulo 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

O, si estuviera ejecutando con la biblioteca de controladores nativos de MySQL (php-mysqlnd), obtendría el siguiente error:

$ 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

Además, también habría otro problema que vería con respecto al juego de caracteres:

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

Soluciones y alternativas

Complemento de autenticación

Ni php-mysqlnd ni la biblioteca php-mysql para PHP5 admiten el nuevo método de autenticación para MySQL 8.0. A partir de MySQL 8.0.4, el método de autenticación se cambió a 'caching_sha2_password', que ofrece un hash de contraseña más seguro en comparación con 'mysql_native_password', que es el predeterminado en las versiones anteriores.

Para permitir la compatibilidad con versiones anteriores en nuestro MySQL 8.0. Dentro del archivo de configuración de MySQL, agregue la siguiente línea en la sección [mysqld]:

default-authentication-plugin=mysql_native_password

Reinicie el servidor MySQL y debería estar bien. Si el usuario de la base de datos se creó antes de los cambios anteriores, por ejemplo, a través de una copia de seguridad y restauración, vuelva a crear el usuario mediante las instrucciones DROP USER y CREATE USER. MySQL seguirá el nuevo complemento de autenticación predeterminado al crear un nuevo usuario.

Discordancia de versión secundaria

Con el paquete php-mysql, si comprobamos la versión de la biblioteca instalada, notaremos la diferencia:

$ 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

La biblioteca PHP está compilada con MariaDB 5.5.60 libmysqlclient, mientras que la versión de la API del cliente está en la versión 5.6.28, proporcionada por el paquete percona-server-shared-compat. A pesar de la advertencia, aún puede obtener una respuesta correcta del servidor.

Para suprimir esta advertencia sobre la discrepancia de la versión de la biblioteca, use el paquete php-mysqlnd, que no depende de la biblioteca MySQL Client Server (libmysqlclient). Esta es la forma recomendada, como se indica en la documentación de MySQL.

Para reemplazar la biblioteca php-mysql con php-mysqlnd, simplemente ejecute:

$ yum remove php-mysql
$ yum install php-mysqlnd
$ systemctl restart httpd

Si reemplazar php-mysql no es una opción, el último recurso es compilar PHP con la biblioteca MySQL 8.0 Client Server (libmysqlclient) manualmente y copiar los archivos de biblioteca compilados en el directorio /usr/lib64/php/modules/, reemplazando el antiguo mysqli. entonces, mysql.so y pdo_mysql.so. Esto es un poco complicado con pocas posibilidades de éxito, principalmente debido a las dependencias obsoletas de los archivos de encabezado en la versión actual de MySQL. Se requiere conocimiento de programación para evitar eso.

Conjunto de caracteres incompatible

A partir de MySQL 8.0.1, MySQL ha cambiado el conjunto de caracteres predeterminado de latin1 a utf8mb4. El conjunto de caracteres utf8mb4 es útil porque hoy en día la base de datos tiene que almacenar no solo caracteres de idioma sino también símbolos, emojis recién introducidos, etc. Charset utf8mb4 es la codificación UTF-8 del conjunto de caracteres Unicode que usa de uno a cuatro bytes por carácter, en comparación con el estándar utf8 (también conocido como utf8mb3) que usa de uno a tres bytes por carácter.

Muchas aplicaciones heredadas no se crearon sobre el conjunto de caracteres utf8mb4. Por lo tanto, sería bueno si cambiamos la configuración de caracteres para el servidor MySQL a algo comprensible para nuestro controlador PHP heredado. Agregue las siguientes dos líneas en la configuración de MySQL en la sección [mysqld]:

collation-server = utf8_unicode_ci
character-set-server = utf8

Opcionalmente, también puede agregar las siguientes líneas en el archivo de configuración de MySQL para agilizar el acceso de todos los clientes para usar utf8:

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

No olvide reiniciar el servidor MySQL para que los cambios surtan efecto. En este punto, nuestra aplicación debería funcionar con MySQL 8.0.

Eso es todo por ahora. Comparta sus comentarios con nosotros en la sección de comentarios si tiene otros problemas para mover aplicaciones heredadas a MySQL 8.0.