C’est au FOSDEM de cette année qui a eu lieu ces 2 et 3 février à Bruxelles que le sujet a été abordé à nouveau par Thomas Vondra, un ingénieur de base de données et contributeur au projet PostgreSQL. Il s’agit de l’implémentation de fsync au sein du gestionnaire de base de données PostgreSQL. D’après ces propos, fsync() ne marche pas réellement comme on le pense sur Linux et d’autres systèmes BSD et peut ainsi avoir des conséquences potentiellement désastreuses pour la durabilité/cohérence des données.
Le paramètre fsync() permet de transférer toutes les données internes modifiées d’un fichier référencé par le descripteur de fichier fd (c'est-à-dire les pages de cache tampon modifiées) vers le périphérique de disque (ou un autre périphérique de stockage permanent), de sorte que toutes les informations modifiées puissent être récupérées même après une panne du système ou son redémarrage. Cela inclut l'écriture ou le vidage d'un cache de disque, le cas échéant. L'appel est bloqué jusqu'à ce que l'appareil signale que le transfert est terminé. Seulement, ce n’est pas exactement ce que fait la fonction avec le serveur de base de données PostgreSQL.
Si ce paramètre est activé, indique la documentation du serveur PostgreSQL, ce dernier essayera de s’assurer que les mises à jour sont écrites physiquement sur le disque en émettant des appels fsync() système ou diverses méthodes équivalentes. Cela garantit que le cluster de base de données peut retrouver un état cohérent après une panne matérielle ou du système d'exploitation. Toujours dans cette documentation, il est noté que, bien que la désactivation de fsync() soit souvent un avantage en termes de performances, cela peut entraîner une corruption irrémédiable des données en cas de panne de courant ou de panne du système.
Il est donc conseillé de désactiver cette fonction fsync si vous pouvez facilement recréer toute votre base de données à partir de données externes dans le cas contraire ne le faites pas. Le problème abordé par Vondra a été signalé pour la première fois en mars de l’année dernière par Craig Ringer, un ingénieur en base de données. Il prévenait que la gestion des erreurs fsync() par PostgreSQL est dangereuse et risque de provoquer une perte de données sur XFR. Ensuite Jonathan Corbet, un autre ingénieur en base de données a apporté plus d’explications sur le sujet en avril dernier.
PostgreSQL, dit-il, suppose qu’un appel réussi à fsync() indique que toutes les données écrites depuis le dernier appel réussi sont passées en toute sécurité au stockage persistant. Mais ce n'est pas ce que fait le noyau. Lorsqu'une écriture d'E/S en mémoire tampon échoue en raison d'une erreur matérielle, les systèmes de fichiers répondent différemment, mais ce comportement implique généralement de supprimer les données des pages affectées et de les marquer comme étant propres. Ainsi, une lecture des blocs qui viennent d'être écrits retournera probablement autre chose que les données écrites.
De plus, continue-t-il dans son explication, même avant que la communauté n'entre dans la discussion, il était devenu évident que la situation n'était pas aussi simple qu'il n’y paraissait. Thomas Munro a indiqué que Linux ne se comportait pas de la sorte. OpenBSD et NetBSD peuvent également ne pas rapporter d’erreurs d’écriture dans l’espace utilisateur. Et il s’avère que la façon dont PostgreSQL traite les E/S en mémoire tampon complique considérablement l’image. Le serveur PostgreSQL s'exécute comme un ensemble de processus dont beaucoup peuvent effectuer des E/S sur les fichiers de base de données.
Le travail d'appel de fsync() cependant, est traité dans un processus unique “checkpointer", qui consiste à maintenir le stockage sur disque dans un état cohérent pouvant être restauré à partir d'échecs. Le point de contrôle ne laisse normalement pas tous les fichiers pertinents ouverts. Il doit donc souvent ouvrir un fichier avant d'appeler fsync() dessus. C’est là que le problème se pose, souligne-t-il. Même dans les noyaux 4.13 et ultérieurs, le checkpointer ne verra aucune erreur survenue avant l’ouverture du fichier. Si quelque chose de grave se produit avant l'appel de la fonction open() du checkpointer, le paramètre fsync() retournera simplement un succès.
Alors, comment résoudre un tel problème ?
Avant cette question, plusieurs propositions avaient été faites pour résoudre le problème, mais ces solutions étaient toutes à court terme. Certains internautes ont pensé à adopter le mécanisme de la gestion des entrées/sorties mises en place par Google (le noyau a été instrumenté pour signaler les erreurs d'E/S via un socket netlink. Un processus dédié reçoit ces notifications et répond en conséquence) et d’autres ont proposé de définir un indicateur dans le superbloc du système de fichiers lorsqu’une erreur d’E/S se produit.
Une autre proposition était de répondre à une erreur d'E/S en marquant le fichier lui-même (dans l'inode) comme étant dans un état d'erreur persistante. Cependant, un tel changement éloignerait davantage le comportement de Linux des mandats POSIX et soulèverait d'autres questions notamment : quand et comment cet indicateur serait-il effacé ? Donc, ce changement semble peu probable ou peu envisageable. Au FOSDEM 2019, Vondra a lui aussi, proposé deux solutions temporaires.
La première concerne la modification du noyau de Linux et la seconde demande de déclencher PANIC au sein de PostgreSQL pour tenter d’avoir des rapports d’erreurs un peu plus précis. Lorsqu’on choisira de modifier le noyau, précise-t-il, cela nécessitera sans aucun doute beaucoup de temps, mais il pourrait payer à la fin. Ce travail permettra tout simplement de retravailler le comportement de fsync. La deuxième méthode consiste à activer les messages PANIC dans PostgreSQL pour déclencher des types d’erreurs spécifiques et de pouvoir les imprimer dans les fichiers journaux.
Cette deuxième action nécessite que les postes exécutant le serveur PostgreSQL soient dotés d’une version supérieure ou égale à la version 4.13 du noyau. D’après certains commentaires des internautes, les systèmes de fichiers modernes sont parfois la cause du manque de performance de certaines applications. Selon eux, cela pousse des fois des développeurs d’applications à abandonner l’idée de développer leur solution pour telle ou telle plateforme et dans la plupart des cas, Linux.
Source : FOSDEM, Vidéo de la présentation, LWN.net
Et vous ?
Que pensez-vous de ce problème ?
Quelles autres solutions préconiseriez-vous pour régler le soucis ?
Voir aussi
Disponibilité générale de PostgreSQL 11 : un aperçu des principales fonctionnalités du SGBDRO libre
Microsoft fait l'acquisition de Citus Data l'extension qui transforme PostgreSQL en une base de données distribuée
Emploi développeur 2017 : les SGBD les plus demandés et les mieux payés, MySQL, MongoDB et PostgreSQL plus demandés mais MongoDB et DB2 mieux payés
DB-Engines Ranking : PostgreSQL désigné système de gestion de base de données de l'année 2017, quels étaient vos SGBD préférés en 2017 ?
Microsoft Azure embarque une nouvelle offre NoSQL et deux nouveaux services de bases de données pour un support natif de MySQL et PostgreSQL
Depuis 20 ans, PostgreSQL aurait mal utilisé fsync(), compromettant la cohérence des données,
Des solutions ont été proposées au FOSDEM 2019
Depuis 20 ans, PostgreSQL aurait mal utilisé fsync(), compromettant la cohérence des données,
Des solutions ont été proposées au FOSDEM 2019
Le , par Bill Fassinou
Une erreur dans cette actualité ? Signalez-nous-la !