MariaDB
 sql >> Base de Dados >  >> RDS >> MariaDB

Como executar aplicativos PHP 5 com MySQL 8.0 no CentOS 7


Apesar do PHP 5 ter chegado ao fim da vida útil, ainda existem aplicativos legados criados sobre ele que precisam ser executados em ambientes de produção ou teste. Se você estiver instalando pacotes PHP através do repositório do sistema operacional, ainda há uma chance de você acabar com pacotes PHP 5, por exemplo. Sistema operacional CentOS 7. Dito isso, sempre há uma maneira de fazer com que seus aplicativos legados sejam executados com as versões mais recentes do banco de dados e, assim, aproveitar os novos recursos.

Nesta postagem do blog, mostraremos como podemos executar aplicativos PHP 5 com a versão mais recente do MySQL 8.0 no sistema operacional CentOS 7. Este blog é baseado em uma experiência real com um projeto interno que exigia que o aplicativo PHP 5 fosse executado junto com nosso novo MySQL 8.0 em um novo ambiente. Observe que funcionaria melhor para executar a versão mais recente do PHP 7 junto com o MySQL 8.0 para aproveitar todas as melhorias significativas introduzidas nas versões mais recentes.

PHP e MySQL no CentOS 7


Antes de tudo, vamos ver quais arquivos estão sendo fornecidos pelo pacote 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 padrão, se instalamos os componentes padrão da pilha LAMP vêm com o CentOS 7, por exemplo:
$ yum install -y httpd php php-mysql php-gd php-curl mod_ssl

Você obteria os seguintes pacotes 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

Os seguintes módulos relacionados ao MySQL serão então carregados no PHP:
$ php -m | grep mysql
mysql
mysqli
pdo_mysql

Ao olhar para a versão da API relatada por phpinfo() para clientes relacionados ao MySQL, todos eles correspondem à versão do MariaDB que instalamos:
$ 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

Neste ponto, podemos concluir que o módulo php-mysql instalado é construído e compatível com MariaDB 5.5.60.

Instalando o MySQL 8.0


No entanto, neste projeto, somos obrigados a executar o MySQL 8.0, então escolhemos o Percona Server 8.0 para substituir a instalação padrão existente do MariaDB que temos nesse servidor. Para fazer isso, temos que instalar o Percona Repository e habilitar o repositório 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

No entanto, recebemos o seguinte erro após executar o ú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

O acima simplesmente significa que o pacote compat compartilhado do Percona Server deve tornar obsoleto o mariadb-libs-5.5.60, que é requerido pelos pacotes mariadb-server já instalados. Como este é um novo servidor simples, remover os pacotes existentes do MariaDB não é um grande problema. Vamos removê-los primeiro e depois tentar instalar o Percona Server 8.0 mais uma vez:
$ 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

A remoção de mariadb-libs também removerá outros pacotes que dependem disso do sistema. Nossa principal preocupação são os pacotes php-mysql que serão removidos por causa da dependência do libmysqlclient.so.18 fornecido pelo mariadb-libs. Vamos corrigir isso mais tarde.

Depois disso, devemos ser capazes de instalar o Percona Server 8.0 sem erros:
$ yum install percona-server-server

Neste ponto, aqui estão os pacotes relacionados ao MySQL que temos no 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

Observe que não temos pacotes php-mysql que fornecem módulos para conectar nosso aplicativo PHP com nosso servidor Percona Server 8.0 recém-instalado. Podemos confirmar isso verificando o módulo PHP carregado. Você deve obter uma saída vazia com o seguinte comando:
$ php -m | grep mysql

Vamos instalá-lo novamente:
$ yum install php-mysql
$ systemctl restart httpd

Agora nós os temos e são carregados no PHP:
$ php -m | grep mysql
mysql
mysqli
pdo_mysql

E também podemos confirmar isso observando as informações do PHP via linha 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 a diferença na versão da biblioteca da API do cliente e na versão do cabeçalho da API. Veremos o efeito posterior disso mais tarde durante o teste.

Vamos iniciar nosso servidor MySQL 8.0 para testar nosso aplicativo PHP5. Como o MariaDB usou o datadir em /var/lib/mysql, temos que limpá-lo primeiro, reinicializar o datadir, atribuir a propriedade adequada e iniciá-lo:
$ rm -Rf /var/lib/mysql
$ mysqld --initialize
$ chown -Rf mysql:mysql /var/lib/mysql
$ systemctl start mysql

Pegue a senha raiz temporária do MySQL gerada pelo Percona Server do arquivo de log de erros do 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

Use-o para fazer login durante o primeiro login do usuário [email protected] Temos que alterar a senha temporária para outra coisa antes de podermos executar qualquer outra ação no servidor:
$ mysql -uroot -p
mysql> ALTER USER [email protected] IDENTIFIED BY 'myP455w0rD##';

Em seguida, prossiga para criar nossos recursos de banco de dados exigidos pelo nosso aplicativo:
mysql> CREATE SCHEMA testdb;
mysql> CREATE USER [email protected] IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON testdb.* TO [email protected];

Uma vez feito, importe os dados existentes do backup para o banco de dados ou crie seus objetos de banco de dados manualmente. Nosso banco de dados agora está pronto para ser usado pelo nosso aplicativo.

Erros e avisos


Em nossa aplicação, tínhamos um arquivo de teste simples para garantir que a aplicação é capaz de se conectar via socket, ou seja, localhost na porta 3306 para eliminar todas as conexões de banco de dados via rede. Imediatamente, receberíamos o aviso de incompatibilidade de versão:
$ 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

Ao mesmo tempo, você também encontraria o erro de autenticação com o 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

Ou, se você estivesse executando com a biblioteca de drivers nativos do MySQL (php-mysqlnd), você receberia o seguinte erro:
$ 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

Além disso, haveria também outro problema que você veria em relação ao charset:
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

Soluções e soluções alternativas

Plugin de autenticação


Nem a biblioteca php-mysqlnd nem php-mysql para PHP5 suporta o novo método de autenticação para MySQL 8.0. A partir do MySQL 8.0.4 o método de autenticação foi alterado para 'caching_sha2_password', que oferece um hash de senha mais seguro se comparado ao 'mysql_native_password' que é padrão nas versões anteriores.

Para permitir compatibilidade com versões anteriores em nosso MySQL 8.0. Dentro do arquivo de configuração do MySQL, adicione a seguinte linha na seção [mysqld]:
default-authentication-plugin=mysql_native_password

Reinicie o servidor MySQL e você deve estar bem. Se o usuário do banco de dados foi criado antes das alterações acima, por exemplo, por meio de backup e restauração, recrie o usuário usando as instruções DROP USER e CREATE USER. O MySQL seguirá o novo plugin de autenticação padrão ao criar um novo usuário.

Incompatibilidade de versão secundária


Com o pacote php-mysql, se verificarmos a versão da biblioteca instalada, notamos a diferença:
$ 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

A biblioteca PHP é compilada com MariaDB 5.5.60 libmysqlclient, enquanto a versão da API do cliente está na versão 5.6.28, fornecida pelo pacote percona-server-shared-compat. Apesar do aviso, você ainda pode obter uma resposta correta do servidor.

Para suprimir este aviso de incompatibilidade de versão da biblioteca, use o pacote php-mysqlnd, que não depende da biblioteca MySQL Client Server (libmysqlclient). Esta é a maneira recomendada, conforme indicado na documentação do MySQL.

Para substituir a biblioteca php-mysql por php-mysqlnd, basta executar:
$ yum remove php-mysql
$ yum install php-mysqlnd
$ systemctl restart httpd

Se substituir php-mysql não for uma opção, o último recurso é compilar o PHP com a biblioteca MySQL 8.0 Client Server (libmysqlclient) manualmente e copiar os arquivos da biblioteca compilada no diretório /usr/lib64/php/modules/, substituindo o antigo mysqli. então, mysql.so e pdo_mysql.so. Isso é um pouco complicado com pequena chance de taxa de sucesso, principalmente devido a dependências obsoletas de arquivos de cabeçalho na versão atual do MySQL. Conhecimento de programação é necessário para contornar isso.

Charset incompatível


A partir do MySQL 8.0.1, o MySQL mudou o conjunto de caracteres padrão de latin1 para utf8mb4. O conjunto de caracteres utf8mb4 é útil porque hoje em dia o banco de dados precisa armazenar não apenas caracteres de idioma, mas também símbolos, emojis recém-introduzidos e assim por diante. Charset utf8mb4 é a codificação UTF-8 do conjunto de caracteres Unicode usando um a quatro bytes por caractere, se comparado ao utf8 padrão (também conhecido como utf8mb3) que usa de um a três bytes por caractere.

Muitos aplicativos legados não foram construídos sobre o conjunto de caracteres utf8mb4. Portanto, seria bom se alterássemos a configuração de caracteres do servidor MySQL para algo compreensível pelo nosso driver PHP legado. Adicione as duas linhas a seguir na configuração do MySQL na seção [mysqld]:
collation-server = utf8_unicode_ci
character-set-server = utf8

Opcionalmente, você também pode adicionar as seguintes linhas no arquivo de configuração do MySQL para simplificar todo o acesso do cliente para usar utf8:
[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

Não se esqueça de reiniciar o servidor MySQL para que as alterações tenham efeito. Neste ponto, nosso aplicativo deve estar se dando bem com o MySQL 8.0.

Por enquanto é isso. Compartilhe qualquer feedback conosco na seção de comentários se você tiver outros problemas ao mover aplicativos legados para o MySQL 8.0.