Arrêtez d'utiliser les fonctions mysql_*() !

20 novembre 2012php, MySQL

L’extension PHP ext/mysql est celle qui est historiquement utilisée pour accéder, depuis PHP, à une base de données MySQL : c’est elle qui fournit l’ensemble des fonctions mysql_*() (msqyl_connect(), mysql_query(), mysql_real_escape_string(), …)

ext/mysql, l’extension “historique”

ext/mysql a été introduite dès PHP 2.0 : historiquement parlant, c’est une des plus anciennes extensions fournies par PHP, elle a pour ainsi dire toujours été considérée comme “étant là”, et en ne généralisant probablement pas tant que ça, nous l’avons tous utilisé un jour ou l’autre.

Une extension manquant de fonctionnalités, et plus tellement maintenue

Cela dit, cela fait maintenant plusieurs années que ext/mysql n’est plus en développement actif : en résumant quelque peu, cette extension ne reçoit que des correctifs de sécurité (et il n’y en n’a pas eu tellement ces dernières années), et ne bénéficie plus d’évolution, que ce soit ajout de nouvelles fonctionnalités ou optimisations.


En fait, l’API exportée par ext/mysql ne supporte pas les nouveautés qui ont été introduites par MySQL 4.1 (MySQL 4.1.0 a été publiée en 2003, et le gros des versions releases date s’étale entre 2004 et 2006, avec quelques corrections de bugs jusque 2008) et versions supérieures.

En particulier, ext/mysql ne fournit pas de support pour :

  • Les requêtes préparées (prepared statements), que ce soit côté client ou côté serveur,
  • Les procédures stockées,
  • L’exécution de requêtes multiples,
  • Les transactions (il est tout de même possible d’invoquer les instructions SQL begin/commit/rollback comme des requêtes SQL, cela dit),
  • Les requêtes non-bloquantes.

Autrement dit, en 2012, ext/mysql, ce n’est plus vraiment la pointe du progrès !


En conséquence, l’introduction de la section MySQL du manuel de PHP dit fort clairement (je cite) :

Cette extension n’est pas recommandé pour écrire du nouveau code.
A la place, soit l’extension mysqli ou PDO_MySQL devrait être utilisée.

D’ailleurs, pour compléter, suite à la discussion ext/mysql updates (~deprecated) commencée en avril 2012 sur la mailing-list de l’équipe de documentation, et au ticket #62213: Soft-deprecation notices for ext/mysql, le même type d’avertissement se retrouve sur la documentation de chaque fonction de l’extension ext/mysql, avec des liens vers les alternatives proposées par ext/mysqli et ext/pdo_mysql :

La documentation de mysql_connect() renvoit vers mysqli_connect() et PDO::__construct()

Ou, pour ceux d’entre vous qui préférent la version anglaise de la documentation1 :

La documentation de mysql_connect() renvoit vers mysqli_connect() et PDO::__construct()

Une extension qui pourrait “prochainement” disparaitre ?

ext/mysql étant plutôt “obsolète”, du moins en termes de fonctionnalités et de maintenance, le sujet d’une éventuelle suppression de cette extension revient régulièrement sur le tapis.

Juin 2010 : une idée levée

Par exemple, en juin 2010, au moment où le déplacement de ext/sqlite2 du trunk de PHP vers PECL était discuté, des voix s’élevaient déjà pour demander à ce qu’il en soit de même pour ext/mysql ; par exemple, vous pouvez jeter un coup d’oeil à ces deux mails sur internals@ :

Le sujet ne va pas bien plus loin ; une idée levée, mais rapidement mise de côté, en somme.

Juillet 2011 : le sujet revient ; et fait parler de lui un peu plus largement

Plus proche de nous, en juillet 2011, le sujet est remis sur le devant de la scène :

Cette fois, le sujet attire plus l’attention — mais, une seconde fois, aucune action concrète ne suit.

Avril 2012 : première action concrète : la documentation est mise à jour

J’en parlais un peu plus haut : en avril 2012, nouvelle discussion, sur la mailing-list de l’équipe gérant la documentation de PHP : ext/mysql updates (~deprecated).

Cette fois-ci, cette discussion est suivie d’un effet : la documentation de chaque fonction de ext/mysql explique que cette extension ne devrait plus être utilisée, et renvoit vers les équivalents proposés par ext/mysqli et ext/pdo_mysql.

Novembre 2012 : “RFC: ext/mysql deprecation”

Enfin, ces derniers jours (la discussion a commencé le 12 novembre), une fois de plus, le sujet a été relancé.

Cette fois-ci, les choses sont faites de manière un peu plus formelle, puisque Adam Harvey a choisi de suivre le processus mis en place depuis un peu plus d’un an, en rédigeant une RFC, et en postant en parallèle sur la mailing-list des développeurs de PHP pour encourager à la discussion.

Cette fois-ci, la discussion semble bien lancée, puisqu’elle en est à plus de 120 mails en une semaine ; aucune décision n’a encore été prise, mais, dans les grandes lignes, on peut être amené à penser que :

  • Un jour, l’extension ext/mysql va disparaitre du coeur de PHP,
  • Peut-être pour être migrée vers PECL — ce qui est une suite logique pour une extension qui sort du coeur de PHP — où elle trouvera peut-être des mainteneurs s’il s’avère qu’elle est encore utile dans certains cas.
  • Un jour, probablement dans la version précédent cette suppression, l’extension ext/mysql sera officiellement marquée comme déprécié2 — ce qui signifie que l’utiliser devrait lever des avertissements de type E_DEPRECATED
  • Et enfin, il est nécessaire de communiquer3 sur le fait que ext/mysql n’est plus la solution de choix lorsque l’on veut interroger un serveur MySQL : ext/mysqli et ext/pdo_mysql sont à privilégier.

Dans l’ensemble, les différents intervenants ont l’air d’accord sur ces points ; les points de discussion restant portent surtout sur les versions de PHP pour lesquelles ces changements devraient être appliqués :

  • Est-ce que, dès maintenant, la documentation doit insister plus lourdement sur le fait que ext/mysql disparaitra un jour ?
  • Est-ce que les fonctions mysql_*() doivent lever des avertissements E_DEPRECATED dès PHP 5.5 ? Ou à partir de PHP 5.6 ?
  • Dans quel cas est-ce que des avertissements E_DEPRECATED devront être levés ? Lors du chargement de l’extension ext/mysql ? Lors de la connexion à une base de donnée avec mysql_connect() et/ou mysql_pconnect() ? Ou à chaque appel de fonction mysql_*() ?
  • Est-ce que ext/mysql doit être déplacée vers PECL (et donc, ne plus être fournie avec PHP) dès PHP 5.6 ? Ou à partir de la version suivante ?

Bref, comme je disais : aucune décision n’a encore été prise ; mais il semblerait que, cette fois-ci, il y ait une véritable volonté de faire évoluer les choses !

Quoi qu’il en soit, il est plus que temps de cesser d’utiliser ext/mysql, en particulier pour les nouveaux projets — et de passer à MySQLi ou à PDO !

Voici quelques liens correspondant :

L’extension ext/mysqli

L’extension ext/mysqli — comme MySQL improved — a fait son apparition avec PHP 5.0 ; elle a été développée pour tirer parti des nouvelles fonctionnalités apportées par MySQL >= 4.1.

Cette extension a un grand nombre d’avantages, et fournit plusieurs améliorations, par rapport à ext/mysql :

  • Support des requêtes préparées (prepared statements),
  • Support des transactions (sans avoir à jouer “à la main” des requêtes begin/commit/rollback),
  • Deux interfaces : procédurale, et orientée objet,
  • Support des requêtes multiples (plusieurs requêtes SQL en un seul envoi au serveur).

Notez que si vous utilisez le pilote natif MysQL mysqlnd (ajouté en PHP 5.3, et activé par défaut à partir de PHP 5.4) comme bibliothèque de connexion à MySQL (au lieu de libmysql), en dessous de l’extension ext/mysqli, vous bénéficierez aussi :

  • De la possibilité de jouer des requêtes en arrière-plan, en jouant avec mysqli_query() et l’option MYSQLI_ASYNC :
    • A partir de votre code PHP, envoyez une requête longue au serveur MySQL,
    • pendant qu’elle est jouée du côté du serveur MySQL, continuez l’exécution de votre code PHP,
    • et utilisez son résultat plus tard, une fois qu’elle sera terminée.
    • Autrement dit : votre script PHP n’attend plus systématiquement “à ne rien faire” pendant qu’une requête SQL est jouée.
  • Et de plus de statistiques.

En somme, si votre application PHP doit communiquer avec une base de données MySQL, en particulier si vous n’avez pas besoin que votre code soit compatible avec un autre SGBD, il est fortement recommandé d’utiliser l’extension ext/mysqli.

Et PDO, alors ?

L’extension PDO, introduite avec PHP 5.1, a comme avantage majeur de proposer une API qui permet d’interroger plusieurs moteurs de bases de données différents, sans avoir à modifier votre code PHP — pour peu que vos requêtes SQL se limitent au sous-ensemble de SQL compris par ces différents moteurs.

Il est tout à fait envisageable, en utilisant PDO, d’écrire du code qui fonctionne avec MySQL et PostgreSQL, sans avoir à effectuer de remaniement important de code.

Le contre-coup, directement lié à cette API simple et portable, est que PDO ne supporte pas ou peu les fonctionnalités avancées, spécifiques à chaque moteur de bases de données — par exemple, avec MySQL, PDO ne supporte pas les requêtes en arrière-plan, et ne permet pas d’obtenir autant de statistiques que ext/mysqli.

Autrement dit, si vous n’avez besoin de supporter que MySQL, et/ou si vous voulez profiter des fonctionnalités avancées que PDO ne supporte pas, vous aurez tendance à privilégier l’utilisation de ext/mysqli.

Voir aussi

> We, from the MySQL Connector Team at Oracle, add new features to mysqli (and eventually PDO) only, though, for quite some time already.
> <br />Users should use mysqli for having access to everything MySQL has to offer.

 * [Converting to MySQLi](https://wikis.oracle.com/display/mysql/Converting+to+MySQLi)
 * L'avis de [@nacin](https://twitter.com/nacin), Lead Developper de Wordpress, sur la RFC proposant de marquer `ext/mysql` comme dépréciée :

<span style="display: block; text-align: center;">[![...](/public/php-arretez-utiliser-fonctions-mysql/small-tweet-nacin-wordpress-mysql-e_deprecated.png)](/public/php-arretez-utiliser-fonctions-mysql/tweet-nacin-wordpress-mysql-e_deprecated.png)</span>

 * D'ailleurs, même si une partie du texte du ticket est fausse, il y a déjà du travail en cours côté Wordpress : [Use PDO for MySQL queries when PDO is available](http://core.trac.wordpress.org/ticket/21663)
 * Côté eZ Publish aussi, les développeurs ont tendance à [s'éloigner de `ext/mysql`](https://github.com/ezsystems/ezpublish/compare/e00a2c5cfef6776e0b8d8a330b1f6cb397b1ec0e~...485c7054e2f6a381f6f562797e6d0c1cce2c59f2).


Si la qualité de la documentation française ne vous convient pas, vous pouvez facilement participer à son amélioration ; par exemple, en utilisant [l'éditeur en ligne](https://edit.php.net/), qui vous permet de modifier les sources de la documentation sans même avoir à les extraire depuis le repository SVN.
Oui, je sais, "dépréciée" est une mauvaise traduction de "deprecated", et je devrais écrire "obsolète"... désolé, mauvaise habitude.
<br />*(D'un autre côté, à chaque fois que je lis/entends "expression régulière" au lieu de "expression rationelle", je m'étrangle ^^)*

  1. “` D’où cet article, qui a purement pour but de communiquer autour du fait que ext/mysql n’est plus, depuis plusieurs années déjà, “la meilleure façon” de se connecter à un serveur MySQL. 

Vous avez apprécié cet article ? Faites-le savoir !

Ce blog a récemment été migré vers un générateur de sites statiques et je n'ai pas encore eu le temps de remettre un mécanisme de commentaires en place.

Avec un peu de chance, je parviendrai à m'en occuper d'ici quelques semaines ;-)