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\
.
Sinon configurez disk
drive
\Properties\Hardware\Properties\Policies\Enable
write caching on the diskwal_sync_method
à
fsync
ou fsync_writethrough
pour
désactiver le cache en écriture.
Sur macOS, 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, 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_xact
, 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.