Documentation PostgreSQL 8.3.23 > Administration du serveur > Fiabilité et journaux de transaction > Configuration des journaux de transaction | |
Validation asynchrone (Asynchronous Commit | Vue interne des journaux de transaction |
Il y a plusieurs paramètres de configuration associés aux journaux de transaction qui affectent les performances de la base de données. Cette section explique leur utilisation. Consultez le Chapitre 18, Configuration du serveur pour des détails sur la mise en place de ces paramètres de configuration.
Dans la séquence des transactions, les points de contrôles (appelés checkpoints) sont des points qui garantissent que les fichiers de données ont été mis à jour avec toutes les informations enregistrées dans le journal avant le point de contrôle. Au moment du point de contrôle, toutes les pages de données non propres sont écrites sur le disque et une entrée spéciale, pour le point de contrôle, est écrite dans le journal. En cas de défaillance, la procédure de récupération recherche le dernier enregistrement d'un point de vérification dans les traces (enregistrement connus sous le nom de « redo log ») à partir duquel il devra lancer l'opération REDO. Toute modification effectuée sur les fichiers de données avant ce point est sûre d'avoir été enregistrée sur disque. Du coup, après qu'un point de vérification est réalisé, tous les segments représentant des journaux de transaction précédant celui contenant le « redo record » ne sont plus nécessaires et peuvent être soit recyclés soit supprimés (quand l'archivage des journaux de transaction est activé, ces derniers doivent être archivés avant d'être recyclés ou supprimés).
Le processus d'écriture en tâche de fond lance automatiquement un point de contrôle de temps en temps : tous les checkpoint_segments journaux de transaction ou dès que checkpoint_timeout secondes se sont écoulées. Les paramètres par défaut sont respectivement de trois journaux et de 300 secondes. Il est également possible de forcer la création d'un point de contrôle en utilisant la commande SQL CHECKPOINT.
La réduction de checkpoint_segments et/ou checkpoint_timeout implique des points de contrôle plus fréquents. Cela permet une récupération plus rapide après défaillance puisqu'il y a moins d'écritures à synchroniser. Cependant, il faut équilibrer cela avec l'augmentation du coût d'écriture des pages de données modifiées. Si full_page_writes est configuré (ce qui est la valeur par défaut), il reste un autre facteur à considérer. Pour s'assurer de la cohérence des pages de données, la première modification d'une page de données après chaque point de vérification résulte dans le traçage du contenu entier de la page. Dans ce cas, un intervalle de points de vérification plus petit augmentera le volume en sortie des journaux de transaction, diminuant légèrement l'intérêt d'utiliser un intervalle plus petit et impliquant de toute façon plus d'entrées/sorties au niveau disque.
Les points de contrôle sont assez coûteux, tout d'abord parce qu'ils écrivent tous les tampons utilisés, et ensuite parce que cela suscite un trafic supplémentaire dans les journaux de transaction, comme indiqué ci-dessus. Du coup, il est conseillé de configurer les paramètres en relation assez haut pour que ces points de contrôle ne surviennent pas trop fréquemment. Pour une vérification rapide de l'adéquation de vos paramètres, vous pouvez configurer le paramètre checkpoint_warning. Si les points de contrôle arrivent plus rapidement que checkpoint_warning secondes, un message est affiché dans les journaux applicatifs du serveur recommandant d'accroître checkpoint_segments. Une apparition occasionnelle d'un message ne doit pas vous alarmer mais, s'il apparaît souvent, alors les paramètres de contrôle devraient être augmentés. Les opérations en masse, comme les transferts importants de données via COPY, pourraient être la cause de l'apparition d'un tel nombre de messages d'avertissements si vous n'avez pas configuré checkpoint_segments avec une valeur suffisamment haute.
Pour éviter de remplir le système disque avec de très nombreuses écritures de pages, l'écriture des pages modifiés pendant un point de vérification est étalée sur une période de temps. Cette période est contrôlée par checkpoint_completion_target, qui est donné comme une fraction de l'intervalle des points de vérification. Le taux d'entrées/sorties est ajusté pour que le point de vérification se termine quand la fraction donnée de checkpoint_segments journaux de transaction a été consommée ou quand la fraction donné de checkpoint_timeout secondes s'est écoulée (la condition que se verra vérifiée la première). Avec une valeur par défaut de 0,5, PostgreSQL™ peut s'attendre à terminer chaque point de vérification en moitié moins de temps qu'il ne faudra pour lancer le prochain point de vérification. Sur un système très proche du taux maximum en entrée/sortie pendant des opérations normales, vous pouvez augmenter checkpoint_completion_target pour réduire le chargement en entrée/sortie dû aux points de vérification. L'inconvénient de ceci est que prolonger les points de vérification affecte le temps de récupération parce qu'il faudra conserver plus de journaux de transaction si une récupération est nécessaire. Bien que checkpoint_completion_target puisse valoir 1.0, il est bien mieux de la configurer à une valeur plus basse que ça (au maximum 0,9) car les points de vérification incluent aussi d'autres activités en dehors de l'écriture des pages modifiées. Une valeur de 1,0 peut avoir pour résultat des points de vérification qui ne se terminent pas à temps, ce qui aurait pour résultat des pertes de performance à cause de variation inattendue dans le nombre de journaux nécessaires.
Il y aura toujours au moins un journal de transaction et normalement pas plus de (2 + checkpoint_completion_target) * checkpoint_segments + 1 journaux. Chaque journal fait normalement 16 Mo (bien que cette taille puisse être modifiée lors de la compilation du serveur). Vous pouvez utiliser cela pour estimer l'espace disque nécessaire au stockage des journaux de transaction. D'habitude, quand les vieux journaux ne sont plus nécessaires, ils sont recyclés (renommés pour devenir les prochains segments dans une séquence numérotée). S'il y a plus de 3 * checkpoint_segments + 1 fichiers à cause d'un pic temporaire du taux d'écriture des journaux, ceux inutilisés seront effacés au lieu d'être recyclés jusqu'à ce que le système soit en-dessous de cette limite.
Il existe deux fonctions WAL internes couramment utilisées : LogInsert et LogFlush. LogInsert est utilisée pour placer une nouvelle entrée à l'intérieur des tampons WAL en mémoire partagée. S'il n'y a plus d'espace pour une nouvelle entrée, LogInsert devra écrire (autrement dit, déplacer dans le cache du noyau) quelques tampons WAL remplis. Ceci n'est pas désirable parce que LogInsert est utilisée lors de chaque modification bas niveau de la base (par exemple, lors de l'insertion d'une ligne) quand un verrou exclusif est posé sur des pages de données affectées. À cause de ce verrou, l'opération doit être aussi rapide que possible. Pire encore, écrire des tampons WAL peut forcer la création d'un nouveau journal, ce qui peut prendre beaucoup plus de temps. Normalement, les tampons WAL doivent être écrits et vidés par une requête de LogFlush qui est faite, la plupart du temps, au moment de la validation d'une transaction pour assurer que les entrées de la transaction sont écrites vers un stockage permanent. Sur les systèmes avec une importante écriture de journaux, les requêtes de LogFlush peuvent ne pas arriver assez souvent pour empêcher LogInsert d'avoir à écrire lui-même sur disque. Sur de tels systèmes, on devrait augmenter le nombre de tampons WAL en modifiant le paramètre de configuration wal_buffers. Par défaut, le nombre de tampons est de 8. Réhausser cette valeur augmente considérablement l'utilisation de la mémoire partagée. Quand full_page_writes est configuré et que le système est très occupé, configurer cette variable avec une valeur plus importante aide à avoir des temps de réponse plus réguliers lors de la période suivant chaque point de vérification.
Le paramètre commit_delay définit la durée d'endormissement en micro-secondes du processus serveur après l'écriture d'une entrée de validation dans le journal avec LogInsert avant d'exécuter un LogFlush. Ce délai permet aux autres processus du serveur d'ajouter leurs entrées de validation dans le journal afin de tout écrire vers le disque avec une seule synchronisation du journal. Aucune mise en sommeil n'aura lieu si fsync n'est pas disponible ou si moins de commit_siblings autres sessions sont, à ce moment, dans des transactions actives ; cela évite de dormir quand il est improbable qu'une autre session fasse bientôt une validation. Notez que dans la plupart des plate-formes, la résolution d'une requête d'endormissement est de 10 millisecondes, donc un commit_delay différent de zéro et configuré entre 1 et 10000 micro-secondes a le même effet. Les bonnes valeurs pour ce paramètre ne sont pas encore claires ; les essais sont encouragés.
Le paramètre wal_sync_method détermine la façon dont PostgreSQL™ demande au noyau de forcer les mises à jour des journaux de transaction sur le disque. Toutes les options devraient être identiques en terme de fiabilité, avec l'exception de fsync_writethrough, qui peut parfois forcer une écriture du cache disque même si les autres options ne le feront pas. Néanmoins, l'option la plus rapide dépend principalement de la plateforme. Vous pouvez tester leur rapidité avec l'outil src/tools/fsync, qui se trouve dans le répertoire des sources de PostgreSQL. Notez que ce paramètre est ignoré si fsync a été désactivé.
Activer le paramètre de configuration wal_debug (à supposer que PostgreSQL™ ait été compilé avec le support de ce paramètre) permet d'enregistrer chaque appel WAL à LogInsert et LogFlush dans les journaux applicatifs du serveur. Cette option pourrait être remplacée par un mécanisme plus général dans le futur.