Back-End

17 fev, 2017

Diferenças – MySQLi versus PDO versus MySQL, Benchmark para Comparação de desempenho, Segurança e Conversão que funciona em 2016 e 2017

Publicidade

Desde que o PHP 7 foi lançado e o suporte para o PHP 5 foi encerrado, muitas empresas de hospedagem tiraram o PHP 5 de seus servidores, e desenvolvedores PHP foram forçados a migrar seu código para funcionar com PHP 7.

Uma das mudanças do PHP 7 foi a descontinuação da extensão original do MySQL. Os desenvolvedores tiveram que optar por migrar seu código para usar o MySQLi ou e a extensão PDO.

Leia este artigo para saber sobre as diferenças e decidir qual é o melhor para você migrar seu código para trabalhar no PHP 7 ou posterior, bem como aprender sobre alguns pacotes recomendados que usam PDO ou MySQLi para executar propósitos comuns de banco de dados, como backup, segurança, registro de usuário e login, abstração de banco de dados, ORM (Object-Relational Mapping) etc.

1 – PDO versus MySQLi versus MySQL

Como todos sabemos, o MySQL é um sistema de gerenciamento de banco de dados relacionais open source (RDBMS) que usa o Structured Query Language (SQL). O MySQL é um componente central da LAMP Open Source Web application software (e outras pilhas “AMP”): Apache MySQL e PHP.

O MySQL é uma parte essencial de quase todos os aplicativos open source PHP. Bons exemplos para PHP e scripts baseados em MySQL são phpBB, osCommerce e Joomla.

O PHP costumava vir com a extensão original do MySQL built-in que suporta as versões mais antigas do MySQL. No entanto, essa extensão foi reprovada em favor do MySQLi (i de improved/melhorado). Ao mesmo tempo, o PHP continuou a evoluir e a extensão PDO (PHP Data Objects) foi introduzida para se tornar uma interface comum para acessar muitos tipos de banco de dados.

MySQLi é outra das três maneiras de acessar um servidor de banco de dados MySQL. Como a extensão MySQL, o novo MySQLi foi projetado para aproveitar melhor os recursos mais recentes do servidor MySQL.

A extensão PHP Data Objects (PDO) define uma interface leve e comum para acessar bancos de dados em PHP. Cada driver de banco de dados que é suportado pela interface PDO pode expor recursos específicos do banco de dados, bem como funções comuns.

O PDO fornece uma camada de abstração de acesso a dados, o que significa que, independentemente do tipo de banco de dados que você usa, as mesmas funções estão disponíveis para executar consultas e obter resultados. O PDO não fornece uma abstração de banco de dados completa. Isto é, não reescreve consultas SQL nem emula características em falta. Você deve usar um pacote completo de camada de abstração se precisar dessa capacidade.

2 – Diferença para conectar usando MySQLi e PDO

Tanto o PDO quanto o MySQLi oferecem uma Interface Orientada a Objetos para as funções de extensão, mas o MySQLi também oferece uma API processual, o que facilita a compreensão dos novos usuários. Se você estiver familiarizado com a extensão PHP MySQL original, achará a migração para a interface de MySQLi processual mais fácil. Abaixo está um exemplo:

// PDO 
$pdo = new PDO( "mysql:" . "host=localhost;" . "dbname=database",
    'username', 'password');
 
// mysqli, procedural way 
$mysqli = mysqli_connect( 'localhost', 'username', 'password', 'database');
 
// mysqli, object oriented way 
$mysqli = new mysqli( 'localhost', 'username', 'password', 'database');

A principal vantagem do PDO sobre o MySQLi está no suporte ao banco de dados. O PDO suporta 12 diferentes tipos de banco de dados, em oposição ao MySQLi, que suporta apenas MySQL.

Quando você tem que mudar seu projeto para usar outro banco de dados, o PDO torna o processo mais simples. Então, tudo que você tem a fazer é mudar a sequência de conexão e no máximo algumas consultas se elas usam qualquer sintaxe que não seja suportada pelo seu novo banco de dados.

3 – PDO versus Segurança MysQLi usando declarações preparadas

Tanto o PDO quanto o MySQLi fornecem suporte para consultas preparadas. Isso ajuda a evitar problemas de segurança de injeção de SQL, desde que você use somente consultas preparadas para inserir parâmetros dinâmicos nas consultas.

Por exemplo, considere um hacker que tenta injetar SQL malicioso passando um valor forjado para o código de parâmetro de uma solicitação HTTP POST que poderia ser emulada assim:

$_POST['code'] = "'; DELETE FROM products; /*";

Se você não escapar desse valor, ele será inserido na consulta como está, e por isso iria excluir todas as linhas da tabela de produtos.

Uma maneira de tornar as consultas mais seguras evitando a injeção SQL é citar valores de parâmetro de string para inserir caracteres de escape.

// PDO, “manual” escaping

$name = PDO::quote( $_POST['code'] );
$pdo->query( "SELECT id, name FROM products WHERE code = $code" );

// mysqli, “manual” escaping

$name = mysqli_real_escape_string( $_POST['code'] );
$mysqli->query( "SELECT id, name FROM products WHERE name = '$code'" );

PDO :: quote () não só escapa a sequência de caracteres, mas também adiciona aspas. mysqli_real_escape_string() só escapará da string, então você precisará adicionar as aspas manualmente.

// PDO, prepared statement

$pdo->prepare( 'SELECT id, name FROM products WHERE code = :code' );
$pdo->execute( array( ':code' => $_POST['code'] ) );

// mysqli, prepared statements

$query = $mysqli->prepare('SELECT id, name FROM users WHERE code = ?');
$query->bind_param('s', $_POST['code']);
$query->execute();

PDO também suporta consultas do lado do cliente. Isso significa que quando ele prepara uma consulta, ele não precisa se comunicar com o servidor.

Como o MySQLi use declarações preparadas nativas, ele pode realmente ser mais rápido para usar mysqli_real_escape_string em vez de usar declarações preparadas, enquanto ainda é uma solução segura.

4 – PDO vs MySQLi vs MySQL Performance Benchmark

Houve alguns testes de desempenho benchmark PHP MySQL feitos há vários anos por Jonathan Robson, bem como por Radu Potop. Mesmo que esses testes tenham sido realizados com PHP 5.3 e que atualmente estejamos usando o PHP 7 ou posterior, vamos considerar esses resultados como referência.

Basicamente eles mostram que, para consultas SELECT usando instruções preparadas, o MySQLi é executado um pouco mais rápido. Ainda assim, isso pode não ser significativo, dependendo de seus propósitos.

Lembre-se de que, por padrão, o PDO usa emulação de declarações preparadas no lado do cliente. Ao usar declarações preparadas nativas, há uma viagem de ida e volta adicional para o servidor para preparar a instrução, de modo que o tempo de execução geral da consulta pode ser realmente maior do que quando se usam instruções preparadas nativas para executar uma consulta apenas uma vez.

Como mencionado acima, você pode usar a função mysqli_real_escape_string para citar parâmetros dinâmicos como você faria ao usar a extensão original do MySQL. Isso é como emular consultas preparadas da maneira como é feito com PDO, porque você não precisaria executar uma viagem de ida e volta adicional para o servidor para preparar a declaração.

5 – Comparação entre PDO e termos de uso do MySQLi

Enquanto o MySQLi tem suas vantagens acessando os recursos do servidor MySQL, o PDO às vezes tem uma vantagem e pode ser um ajuste melhor para o usuário, dependendo das preferências pessoais e conveniência. Como a maioria das coisas, a opção que funciona melhor depende de para quem você perguntar e para qual situação você precisa de MySQLi ou PDO.

O MySQLi só funciona com bancos de dados MySQL, enquanto o PDO é flexível e capaz de trabalhar com vários sistemas de banco de dados, incluindo IBM, Oracle e MySQL. Se você tem que mudar de banco de dados ou fornecer uma solução independente de banco de dados, usar o MySQLi diretamente não é a melhor opção. Você ainda pode usar o MySQLi em soluções independentes de banco de dados usando uma camada de abstração.

Os parâmetros de ligação com o MySQLi não são tão fáceis ou flexíveis como com o PDO. O MySQLi usa um sistema de parâmetros numerado e não suporta parâmetros nomeados como PDO. O MySQLi tem um bom suporte e manutenção, tornando a transição para o novo sistema segura.

Você será capaz de utilizar novos recursos disponíveis nas versões mais recentes dos servidores MySQL. Essa é uma das maiores vantagens do MySQLi. PDO pode não ter suporte extenso para tirar o máximo proveito dos recursos mais recentes do MySQL.

O processo de instalação do MySQLi não é apenas fácil, mas é automático quando a extensão PHP 5 MySQL que vem incorporada no Windows ou nas distribuições Linux.

6 – Convertendo aplicações MySQL para usar PDO ou MySQLi

Se você tem um projeto usando a extensão antiga do MySQL e precisa convertê-lo para usar MySQLi ou PDO, pode demorar um pouco para reescrevê-lo se você não estava usando uma camada de abstração de banco de dados.

Se você precisa de uma solução rápida e fácil que não requer a alteração de muito do seu código, você pode tentar o pacote PDO ou o MySQLi para usar cada uma dessas extensões por meio de funções wrapper MySQL que chamam mysql_* functions using PDO  por Aziz S. Hussain ou PHP MySQL to MySQLi  por Dave Smith para funções de extensão PDO e MySQLi, respectivamente.

Isso permitirá que você faça seu código rodar no PHP 7 enquanto faz uma migração real de código que não requer um wrapper.

Dave Smith também escreveu um texto sobre como migrar o código mysql para mysqli considerando as diferenças entre essas extensões.

7 – Recomendações de pacotes para uso com PDO e MySQLi

Existem muitos pacotes que você pode usar para propósitos variados para acessar o MySQL usando MySQLi ou PDO.

Abaixo estão alguns dos pacotes PHP mais recentes que fornecem wrappers seguros e eficientes para várias finalidades do PDO.

Backup PDO e sincronização de banco de dados

PHP Multi MySQLDump (Alessandro Quintiliani)

Tabelas de banco de dados Dump MySQL  para download de arquivos.

PHP Backup to WebDav Server (Dmitry Mamontov)

Arquivos de backup e um banco de dados para um servidor WebDav.

PHP Database Synchronize Tables (Ettore Moretti)

Sincroniza tabelas entre dois bancos de dados usando PDO.

DB Backup Class (Raul)

Gera um backup de banco de dados MySQL usando o PDO.

PHP Database Sync (Jacob Fogg)

Sincroniza tabelas de diferentes bases de dados com PDO.

MySQLi Backup Database

Danen MySQL Backup (Gerry Danen)

Cria instruções SQL de backup de banco de dados usando MySQLi.

Ah MySQLi (Atabak Hosein Nia)

Executa consultas comuns do MySQL usando o MySQLi.

DBMysqli (Osama Salama)

Acessa bancos de dados MySQL com mysql e mysqli.

Segurança e autenticação PDO

PHP Secure Token Generator (Aleksandar Zivanovic)

Cria e valida tokens armazenados na tabela MySQL.

PHP OTP Login (Bijaya Kumar Behera)

Autentica usuários usando o endereço MAC do computador.

Segurança e autenticação MySQLi

PHP OAuth API Library with Tutorial Example Client for Any OAuth1 and OAuth2 Server (Manuel Lemos)

Autoriza e acessa APIs usando OAuth.

Registro de usuário PDO e login

Secure PHP Login System (Subin Siby)

Registra e loga usuários utilizando uma base de dados via PDO.

PHP Auth Class (Con vertor)

Registra e loga usuários armazenados em um banco de dados.

PHP Secure Login and Registration (Ashraf Gheith)

Registra e loga usuários em um banco de dados com PDO.

Acesso a banco de dados PDO e abstração

Multiple PHP PDOStatement Iterator (Matthew Daniel)

Itera sobre vários resultados de consultas usando PDO.

PHP PDO OCI (Eustaquio Rangel de Oliveira)

Acessa bancos de dados Oracle usando um wrapper de classe PDO.

DB Abstract Model (Guillermo Murillo)

Executa consultas MySQL chamando procedimentos armazenados.

Acesso a banco de dados MySQLi e abstração

Metabase (Manuel Lemos)

Camada SGBD indepentende da abtração do banco de dados php.

PHP CRUD REST API Server (Bharat Parmar)

Servidor REST API com operações CRUD baseadas em MySQLi.

Extended MySQLi ()

Wrapper de acesso a banco de dados MySQL usando MySQLi.

PDO ORM (Mapeamento Objeto-Relacional)

Tiny PHP ORM Framework (Victor Bolshov)

Mapeia objetos para bancos de dados usando consultas compostas.

Caribu ORM (Maik Greubel)

Mapeia objetos para registros de bancos de dados usando anotações.

Potato ORM (Adeniyi Ibraheem)

Armazena e recupera objetos em bancos de dados usando ORM.

torm (Eustaquio Rangel)

Armazena e recupera objetos usando ActiveRecord.

SlimDb (Marcelo Entraigas)

Acessa diferentes tipos de banco de dados usando PDO.

MySQLi ORM (Mapeamento Objeto-Relacional) (?)

DB Accelerator (Yazan Tommalieh)

Mapeia registros de tabela MySQL para objetos usando MySQLi.

8 – O que usar em um novo projeto: PDO ou MySQLi?

Embora o PDO possa ser ligeiramente mais lento e não tirar o máximo proveito dos recursos do servidor MySQL, pode ser mais simples gravar menos código dependente do banco ao ter um código mais legível usando parâmetros nomeados para consultas preparadas. Então, qualquer opção pode ser boa, dependendo do que você valoriza.

Este artigo tentou dar algum critério que você deve considerar ao decidir qual é o melhor para você.

***

Haseeb Ahmad Basil faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://www.phpclasses.org/blog/post/521-mysqli-vs-pdo-vs-mysql.html.