La nouvelle fonctionnalité Hot Standby de la prochaine version de PostgreSQL 9.0 permet d'exécuter des requêtes sur des nœuds de secours qui ne faisaient auparavant qu'exécuter un processus de récupération. Deux attentes communes que j'ai entendues de la part des utilisateurs anticipant cette fonctionnalité sont qu'elle permettra soit de distribuer de courtes requêtes sur les deux nœuds, soit d'exécuter de longs rapports sur le serveur de secours sans utiliser de ressources sur le maître. Il est possible de faire ces deux choses en ce moment, mais à moins que vous ne compreniez les compromis impliqués dans le fonctionnement de la redondance d'UC, il peut y avoir un comportement imprévu ici.
Requêtes standard de longue durée
L'un des problèmes traditionnels d'une base de données utilisant MVCC, comme PostgreSQL, est qu'une requête de longue durée doit garder ouverte une ressource - appelée instantané dans l'implémentation actuelle de Postgres - pour empêcher la base de données de supprimer les données dont la requête a besoin pour fonctionner. Par exemple, simplement parce qu'un autre client a supprimé une ligne et validé, si une requête déjà en cours d'exécution a besoin de cette ligne pour se terminer, vous ne pouvez pas encore effacer les blocs de disque physique liés à cette ligne. Vous devez attendre qu'il n'y ait plus de requêtes ouvertes qui s'attendent à ce que cette ligne soit visible.
Limites de la redondance d'UC
Si vous avez une requête de longue durée que vous souhaitez que la redondance d'UC s'exécute, plusieurs types de problèmes peuvent survenir lorsque le processus de récupération applique des mises à jour. Celles-ci sont décrites en détail dans la documentation de la redondance d'UC. Certaines de ces mauvaises choses entraîneront l'annulation des requêtes exécutées en veille pour des raisons qui pourraient ne pas être intuitivement évidentes :
- Une mise à jour HOT ou une mise à jour liée à VACUUM arrive pour supprimer quelque chose que la requête s'attend à voir
- Une suppression d'arbre B apparaît
- Il existe un problème de verrouillage entre la requête que vous exécutez et les verrous requis pour que la mise à jour soit traitée.
La situation de verrouillage est difficile à gérer, mais il est peu probable qu'elle se produise en pratique pendant si longtemps si vous exécutez uniquement des requêtes en lecture seule en veille, car celles-ci seront isolées via MVCC. Les deux autres ne sont pas difficiles à rencontrer. La chose de base à comprendre est que tout UPDATE ou DELETE sur le maître peut conduire à interrompre toute requête sur le standby; peu importe si les changements se rapportent même à ce que fait la requête.
Bon, rapide, pas cher :choisissez-en deux
Essentiellement, il y a trois choses que les gens pourraient vouloir prioriser :
- Évitez la limitation du maître :autorisez les xids et les instantanés associés à avancer sans limite sur le maître, afin que VACUUM et le nettoyage similaire ne soient pas freinés par ce que fait le standby
- Requêtes illimitées :exécutez des requêtes en veille pendant une période arbitraire
- Récupération actuelle :gardez le processus de récupération en veille à jour avec ce qui se passe sur le maître, permettant un basculement rapide pour la haute disponibilité
Dans n'importe quelle situation avec Hot Standby, il est littéralement impossible d'avoir les trois à la fois. Vous ne pouvez choisir que votre compromis. Les paramètres réglables disponibles vous permettent déjà d'optimiser de plusieurs manières :
- La désactivation de tous ces paramètres de délai/diffusion optimise la récupération toujours à jour, mais vous découvrirez alors que les requêtes sont plus susceptibles d'être annulées que prévu.
- max_standby_delay optimise les requêtes plus longues, au détriment de la mise à jour de la récupération. Cela retarde l'application des mises à jour au standby une fois que celle qui causera un problème (HOT, VACUUM, B-tree delete, etc.) apparaît.
- vacuum_defer_cleanup_age et certains hacks d'instantanés peuvent introduire une limitation principale pour améliorer les deux autres problèmes, mais avec une interface utilisateur faible pour le faire. vacuum_defer_cleanup_age est en unités d'ID de transaction. Vous devez avoir une idée de la quantité moyenne de taux de désabonnement xid sur votre système par unité de temps pour transformer la façon dont les gens pensent à ce problème ("reportez-vous d'au moins 1 heure pour que mes rapports soient exécutés") en un paramètre pour cette valeur. Le taux de consommation xid n'est tout simplement pas une chose courante ou même raisonnable à mesurer/prédire. Vous pouvez également ouvrir un instantané sur le serveur principal avant de lancer une requête de longue durée sur le serveur de secours. dblink est suggéré dans la documentation de la redondance d'UC comme moyen d'y parvenir. Théoriquement, un démon en attente pourrait être écrit dans le user-land, vivant sur le primaire, pour contourner ce problème également (Simon a une conception de base pour un). Fondamentalement, vous démarrez une série de processus qui acquièrent chacun un instantané, puis dorment pendant un certain temps avant de le publier. En espaçant la durée de leur sommeil, vous pouvez vous assurer que les instantanés xid n'avancent jamais trop rapidement sur le maître. Cela devrait déjà sembler évident à quel point ce serait un piratage terrible.
Améliorations potentielles
Le seul d'entre eux sur lequel vous pouvez vraiment faire quelque chose proprement est de resserrer et d'améliorer l'interface utilisateur pour la limitation principale. Cela transforme cela en un problème traditionnel déjà présent dans la base de données :une requête de longue durée maintient ouvert un instantané (ou au moins limite l'avance des ID de transaction liés à la visibilité) sur le maître, empêchant le maître de supprimer les éléments nécessaires à cette requête pour Achevée. Vous pouvez également considérer cela comme un vacuum_defer_cleanup_age à réglage automatique.
La question est de savoir comment rendre le primaire respecter les besoins des requêtes de longue durée sur le veille . Cela pourrait être possible si plus d'informations sur les exigences de visibilité des transactions du standby étaient partagées avec le maître. Faire ce genre d'échange serait vraiment quelque chose de plus approprié pour la nouvelle implémentation de Streaming Replication à partager. La façon dont un simple serveur Hot Standby est provisionné ne fournit aucun retour vers le maître approprié pour que ces données soient échangées, en plus des approches comme le hack dblink déjà mentionné.
Avec PostgreSQL 9.0 qui vient d'atteindre une quatrième version alpha, il peut y avoir il est encore temps de voir quelques améliorations dans ce domaine avant la version 9.0. Ce serait bien de voir Hot Standby et Streaming Replication vraiment intégrés ensemble d'une manière qui accomplisse des choses qu'aucun des deux n'est entièrement capable de faire par lui-même avant que le codage de cette version ne se fige complètement.