Documentation PostgreSQL 9.3.25 > Administration du serveur > Fiabilité et journaux de transaction | |
Panne pour disque saturé | Write-Ahead Logging (WAL) |
Ce chapitre explique comment les journaux de transaction sont utilisés pour obtenir des traitements efficaces et fiables.
La fiabilité est une propriété importante de tout système de base de données sérieux. PostgreSQL™ fait tout ce qui est en son pouvoir pour garantir une fiabilité à toute épreuve. Un des aspects de cette fiabilité est que toutes les données enregistrées par une transaction validée doivent être stockées dans un espace non volatile, un espace non sensible aux coupures de courant, aux bogues du système d'exploitation et aux problèmes matériels (sauf en cas de problème sur l'espace non volatile, bien sûr). Écrire avec succès les données sur le stockage permanent de l'ordinateur (disque dur ou un équivalent) est habituellement suffisant pour cela. En fait, même si un ordinateur est vraiment endommagé, si le disque dur survit, il peut être placé dans un autre ordinateur avec un matériel similaire et toutes les transactions validées resteront intactes.
Bien que forcer l'enregistrement des données périodiquement sur le disque semble être une opération simple, ce n'est pas le cas. Comme les disques durs sont beaucoup plus lents que la mémoire principale et les processeurs, plusieurs niveaux de cache existent entre la mémoire principale de l'ordinateur et les disques. Tout d'abord, il existe le tampon cache du système d'exploitation, qui met en cache les blocs disque fréquemment utilisés et combine les écritures sur le disque. Heureusement, tous les systèmes d'exploitation donnent un moyen de forcer les écritures du cache disque vers le disque et PostgreSQL™ utilise ces fonctions (voir le paramètre wal_sync_method pour voir comment cela se fait).
Ensuite, il pourrait y avoir un cache dans le contrôleur du disque dur ; ceci est assez commun sur les cartes contrôleur RAID. Certains de ces caches sont write-through, signifiant que les écritures sont envoyées au lecteur dès qu'elles arrivent. D'autres sont write-back, signifiant que les données sont envoyées au lecteur un peu après. De tels caches peuvent apporter une faille dans la fiabilité car la mémoire du cache du disque contrôleur est volatile et qu'elle perdra son contenu à la prochaine coupure de courant. Des cartes contrôleur de meilleure qualité ont des caches avec batterie (BBU), signifiant que la carte dispose d'une batterie qui maintient le courant dans le cache en cas de perte de courant. Une fois le courant revenu, les données seront écrites sur les disques durs.
Et enfin, la plupart des disques durs ont des caches. Certains sont « write-through » alors que d'autres sont « write-back ». Les mêmes soucis sur la perte de données existent pour ces deux types de cache. Les lecteurs grand public IDE et SATA ont principalement des caches « write-back » qui ne survivront pas à une perte de courant. De nombreux SSD sont aussi dotés de caches « write-back » volatiles.
Ces caches peuvent typiquement être désactivés. Néanmoins, la méthode pour le faire dépend du système d'exploitation et du type de disque :
Sur Linux™, les disques IDE et SATA peuvent être vérifiés avec la commande hdparm -I ; le cache en écriture est activé si une étoile (*) se trouve derrière le texte Write cache. hdparm -W 0 peut être utilisé pour désactiver le cache en écriture. Les disques SCSI peuvent être vérifiés en utilisant sdparm. Utilisez sdparm --get=WCE pour vérifier si le cache en écriture est activé et sdparm --clear=WCE pour le désactiver.
Sur FreeBSD™, les disques IDE peuvent être vérifiés avec atacontrol et le cache en écriture désactivé avec hw.ata.wc=0 dans le fichier de configuration /boot/loader.conf ; les disques SCSI peuvent être vérifiés en utilisant camcontrol identify, et le cache en écriture peut être vérifié et modifié en utilisant sdparm quand cette commande est disponible.
Sur Solaris™, le cache disque en écriture est contrôlé par format -e. (Le système de fichiers Solaris ZFS est sûr, y compris quand le cache disque en écriture est activé car il exécute ses propres commandes de vidage du cache.)
Sur Windows™, si wal_sync_method vaut open_datasync (la valeur par défaut), le cache en écriture peut être désactivé en décochant My Computer\Open\disk drive\Properties\Hardware\Properties\Policies\Enable write caching on the disk. Sinon configurez wal_sync_method à fsync ou fsync_writethrough pour désactiver le cache en écriture.
Sur Mac OS X™, le cache en écriture peut être évité en configurant wal_sync_method à fsync_writethrough.
Les disques SATA récents (ceux compatibles ATAPI-6 ou supérieurs) proposent une commande pour vider le cache sur le disque (FLUSH CACHE EXT) alors que les disques SCSI proposent depuis longtemps une commande similaire, SYNCHRONIZE CACHE. Ces commandes ne sont pas directement accessibles à PostgreSQL™, mais certains systèmes de fichiers (comme ZFS, ext4) peuvent les utiliser pour vider les données sur disque pour les disques dont le cache en écriture est activé. Malheureusement, ces systèmes de fichiers se comportent de façon non optimale avec des contrôleurs disque équipés de batterie (BBU, acronyme de Battery-Backed Unit). Dans ce type de configuration, la commande de synchronisation force l'écriture de toutes les données comprises dans le cache sur les disques, éliminant ainsi tout l'intérêt d'un cache protégé par une batterie. Vous pouvez lancer l'outil pg_test_fsync(1), disponible dans le code source de PostgreSQL, pour vérifier si vous êtes affecté. Si vous l'êtes, les améliorations de performance du cache BBU peuvent être de nouveaux obtenues en désactivant les barrières d'écriture dans la configuration du système de fichiers ou en reconfigurant le contrôleur de disque, si cela est possible. Si les barrières d'écriture sont désactivées, assurez-vous que la batterie reste active. Une batterie défectueuse peut être une cause de perte de données. Il reste à espérer que les concepteurs de systèmes de fichiers et de contrôleurs disque finissent par s'attaquer à ce comportement gênant.
Quand le système d'exploitation envoie une demande d'écriture au système de stockage, il ne peut pas faire grand chose pour s'assurer que les données sont arrivées dans un espace de stockage non volatile. Ce travail incombe à l'administrateur : ce dernier doit s'assurer que tous les composants de stockage assurent l'intégrité des données et des métadonnées du système de fichier. Évitez les contrôleurs disques ne disposant pas de caches protégés par batterie. Au niveau du disque, désactivez le cache « write-back » si le disque ne garantit pas que les données seront écrites avant un arrêt. Si vous utilisez des disques SSD, sachez que beaucoup n'honorent pas les commandes de vidage de cache par défaut. Vous pouvez tester la fiabilité du comportement du système disque en utilisant diskchecker.pl.
Un autre risque concernant la perte des données est dû aux opérations d'écriture sur les plateaux du disque. Les plateaux sont divisés en secteur de 512 octets généralement. Chaque opération de lecture ou écriture physique traite un secteur entier. Quand la demande d'écriture arrive au lecteur, elle pourrait contenir des multiples de 512 octets (PostgreSQL™ écrit généralement 8192 octets, soit 16 secteurs, à la fois) et le processus d'écriture pourrait échouer à cause d'une perte de courant à tout moment signifiant que certains octets pourraient être écrits et les autres perdus. Pour se prévenir contre ce type d'échec, PostgreSQL™ écrit périodiquement des images de page complète sur le stockage permanent des journaux de transactions avant de modifier la page réelle sur disque. En effectuant ceci, lors d'une récupération après un arrêt brutal, PostgreSQL™ peut restaurer des pages écrites partiellement à partir des journaux de transactions. Si vous avez un système de fichiers qui vous protège contre les écritures de pages incomplètes (par exemple ZFS), vous pouvez désactiver la création des images de page en utilisant le paramètre full_page_writes. Les contrôleurs disques disposant d'une batterie (BBU pour Battery-Backed Unit) n'empêchent pas les écritures de pages partielles sauf s'ils garantissent que les données sont écrites par pages complètes de 8 Ko.
PostgreSQL™ protège aussi de certaines corruptions de données des supports de stockage qui pourraient se produire suite à des erreurs au niveau matériel ou des problèmes d'usure rencontrés avec le temps, comme par exemple la lecture ou l'écriture de données erronnées.
Chaque enregistrement individuel d'un journal de transactions est protégé par une somme de contrôle CRC-32 (32-bit) qui permet de savoir si le contenu de l'enregistrement est correct. La valeur du CRC est définie à chaque écriture d'un enregistrement dans les journaux de transactions et vérifiée durant la reconstruction de la mémoire, la récupération d'une archive ou encore la réplication.
Les pages de données ne disposent pas de sommes de contrôle par défaut, mais les images des pages complètes stockées dans les enregistrements des journaux de transactions seront protégées. Voir initdb pour les détails sur l'activation des sommes de contrôle sur les pages de données.
Le code vérificateur des structures de données internes comme pg_clog, pg_subtrans, pg_multixact, pg_serial, pg_notify, pg_stat, pg_snapshots ne sont pas directement calculées, même si les pages sont protégées par les écritures de pages complètes. Cependant, lorsque de telles structures de données sont persistentes, les enregistrements fes journaux de transactions sont écrits de manière à ce que les modifications récentes puissent être rapidement reconstruites durant une restauration après incident, et pour cela, ils sont protégés tel que décrit plus haut.
Les fichiers d'état individuels de pg_twophase sont protégés par une somme de contrôle CRC-32.
Les fichiers de données temporaires utilisés pour les grosses requêtes SQL de tri, la matérialisation ou encore les résultats intermédiaires ne sont pas actuellement l'objet d'un calcul de somme de contrôle, bien que la modification de ces fichiers soit consignée dans les enregistrements des journaux de transactions.
PostgreSQL™ ne protége pas contre les erreurs mémoires et il est pris comme hypothèse que vous travaillerez avec de la RAM respectant les standards de l'industrie, incluant les codes des correcteurs d'erreur (ECC) ou une meilleure protection.