Des serveurs de bases de données peuvent travailler ensemble pour permettre à un serveur secondaire de prendre rapidement la main si le serveur principal échoue (haute disponibilité, ou high availability), ou pour permettre à plusieurs serveurs de servir les mêmes données (répartition de charge, ou load balancing). Idéalement, les serveurs de bases de données peuvent travailler ensemble sans jointure.
Il est aisé de faire coopérer des serveurs web qui traitent des pages web statiques en répartissant la charge des requêtes web sur plusieurs machines. Dans les faits, les serveurs de bases de données en lecture seule peuvent également coopérer facilement. Malheureusement, la plupart des serveurs de bases de données traitent des requêtes de lecture/écriture et, de ce fait, collaborent plus difficilement. En effet, alors qu'il suffit de placer une seule fois les données en lecture seule sur chaque serveur, une écriture sur n'importe quel serveur doit, elle, être propagée à tous les serveurs afin que les lectures suivantes sur ces serveurs renvoient des résultats cohérents.
Ce problème de synchronisation représente la difficulté fondamentale à la collaboration entre serveurs. Comme la solution au problème de synchronisation n'est pas unique pour tous les cas pratiques, plusieurs solutions co-existent. Chacune répond de façon différente et minimise cet impact au regard d'une charge spécifique.
Certaines solutions gèrent la synchronisation en autorisant les modifications des données sur un seul serveur. Les serveurs qui peuvent modifier les données sont appelés serveur en lecture/écriture, maître ou serveur primaire. Les serveurs qui suivent les modifications du maître sont appelés standby, ou serveurs esclaves. Un serveur en standby auquel on ne peut pas se connecter tant qu'il n'a pas été promu en serveur maître est appelé un serveur en warm standby, et un qui peut accepter des connections et répondre à des requêtes en lecture seule est appelé un serveur en hot standby.
Certaines solutions sont synchrones, ce qui signifie qu'une transaction de modification de données n'est pas considérée valide tant que tous les serveurs n'ont pas validé la transaction. Ceci garantit qu'un failover ne perd pas de données et que tous les serveurs en répartition de charge retournent des résultats cohérents, quel que soit le serveur interrogé. Au contraire, les solutions asynchrones autorisent un délai entre la validation et sa propagation aux autres serveurs. Cette solution implique une éventuelle perte de transactions lors de la bascule sur un serveur de sauvegarde, ou l'envoi de données obsolètes par les serveurs à charge répartie. La communication asynchrone est utilisée lorsque la version synchrone est trop lente.
Les solutions peuvent aussi être catégorisées par leur granularité. Certaines ne gèrent que la totalité d'un serveur de bases alors que d'autres autorisent un contrôle par table ou par base.
Il importe de considérer les performances dans tout choix. Il y a généralement un compromis à trouver entre les fonctionnalités et les performances. Par exemple, une solution complètement synchrone sur un réseau lent peut diviser les performances par plus de deux, alors qu'une solution asynchrone peut n'avoir qu'un impact minimal sur les performances.
Le reste de cette section souligne différentes solutions de failover, de réplication et de répartition de charge. Un glossaire est aussi disponible.
Le failover (ou bascule sur incident) sur disque partagé élimine la surcharge de synchronisation par l'existence d'une seule copie de la base de données. Il utilise un seul ensemble de disques partagé par plusieurs serveurs. Si le serveur principal échoue, le serveur en attente est capable de monter et démarrer la base comme s'il récupérait d'un arrêt brutal. Cela permet un failover rapide sans perte de données.
La fonctionnalité de matériel partagé est commune aux périphériques de stockage en réseau. Il est également possible d'utiliser un système de fichiers réseau bien qu'il faille porter une grande attention au système de fichiers pour s'assurer qu'il a un comportement POSIX complet (voir Section 17.2.2, « Utilisation de systèmes de fichiers réseaux »). Cette méthode comporte une limitation significative : si les disques ont un problème ou sont corrompus, le serveur primaire et le serveur en attente sont tous les deux non fonctionnels. Un autre problème est que le serveur en attente ne devra jamais accéder au stockage partagé tant que le serveur principal est en cours d'exécution.
Il est aussi possible d'utiliser cette fonctionnalité d'une autre façon avec une réplication du système de fichiers, où toutes les modifications d'un système de fichiers sont renvoyées sur un système de fichiers situé sur un autre ordinateur. La seule restriction est que ce miroir doit être construit de telle sorte que le serveur en attente dispose d'une version cohérente du système de fichiers -- spécifiquement, les écritures sur le serveur en attente doivent être réalisées dans le même ordre que celles sur le maître. DRBD™ est une solution populaire de réplication de systèmes de fichiers pour Linux.
Les serveurs warm et hot standby (voir Section 25.2, « Serveurs de Standby par transfert de journaux ») peuvent conserver leur cohérence en lisant un flux d'enregistrements de WAL. Si le serveur principal échoue, le serveur standby contient pratiquement toutes les données du serveur principal et peut rapidement devenir le nouveau serveur maître. Ça peut être synchrone mais ça ne peut se faire que pour le serveur de bases complet.
Un serveur de standby peut être implémenté en utilisant la recopie de journaux par fichier (Section 25.2, « Serveurs de Standby par transfert de journaux ») ou la streaming replication (réplication en continu, voir Section 25.2.5, « Streaming Replication »), ou une combinaison des deux. Pour des informations sur le hot standby, voyez Section 25.5, « Hot Standby »..
Une configuration de réplication maître/esclave envoie toutes les requêtes de modification de données au serveur maître. Ce serveur envoie les modifications de données de façon asynchrone au serveur esclave. L'esclave peut répondre aux requêtes en lecture seule alors que le serveur maître est en cours d'exécution. Le serveur esclave est idéal pour les requêtes vers un entrepôt de données.
Slony-I™ est un exemple de ce type de réplication, avec une granularité par table et un support des esclaves multiples. Comme il met à jour le serveur esclave de façon asynchrone (par lots), il existe une possibilité de perte de données pendant un failover.
Avec les middleware de réplication basés sur les instructions, un programme intercepte chaque requête SQL et l'envoie à un ou tous les serveurs. Chaque serveur opère indépendamment. Les requêtes en lecture/écriture doivent être envoyées à tous les serveurs pour que chaque serveur reçoive les modifications. Les requêtes en lecture seule ne peuvent être envoyées qu'à un seul serveur, ce qui permet de distribuer la charge de lecture.
Si les requêtes sont envoyées sans modification, les fonctions comme random(), CURRENT_TIMESTAMP ainsi que les séquences ont des valeurs différentes sur les différents serveurs. Cela parce que chaque serveur opère indépendamment alors que les requêtes SQL sont diffusées (et non les données modifiées). Si cette solution est inacceptable, le middleware ou l'application doivent demander ces valeurs à un seul serveur, et les utiliser dans des requêtes d'écriture. Une autre solution est d'utiliser cette solution de réplication avec une configuration maître-esclave traditionnelle, c'est à dire que les requêtes de modification de données ne sont envoyées qu'au maître et sont propagées aux esclaves via une réplication maître-esclave, pas par le middleware de réplication. Il est impératif que toute transaction soit validée ou annulée sur tous les serveurs, éventuellement par validation en deux phases (PREPARE TRANSACTION(7) et COMMIT PREPARED(7). Pgpool-II™ et Continuent Tungsten™ sont des exemples de ce type de réplication.
Pour les serveurs qui ne sont pas connectés en permanence, comme les ordinateurs portables ou les serveurs distants, conserver la cohérence des données entre les serveurs est un challenge. L'utilisation de la réplication asynchrone multi-maîtres permet à chaque serveur de fonctionner indépendamment. Il communique alors périodiquement avec les autres serveurs pour identifier les transactions conflictuelles. La gestion des conflits est alors confiée aux utilisateurs ou à un système de règles de résolution. Bucardo est un exemple de ce type de réplication.
Dans les réplications synchrones multi-maîtres, tous les serveurs acceptent les requêtes en écriture. Les données modifiées sont transmises du serveur d'origine à tous les autres serveurs avant toute validation de transaction.
Une activité importante en écriture peut être la cause d'un verrouillage excessif et conduire à un effondrement des performances. Dans les faits, les performances en écriture sont souvent pis que celles d'un simple serveur.
Tous les serveurs acceptent les requêtes en lecture.
Certaines implantations utilisent les disques partagés pour réduire la surcharge de communication.
Les performances de la réplication synchrone multi-maîtres sont meilleures lorsque les opérations de lecture représentent l'essentiel de la charge, alors que son gros avantage est l'acceptation des requêtes d'écriture par tous les serveurs -- il n'est pas nécessaire de répartir la charge entre les serveurs maîtres et esclaves et, parce que les modifications de données sont envoyées d'un serveur à l'autre, les fonctions non déterministes, comme random(), ne posent aucun problème.
PostgreSQL™ n'offre pas ce type de réplication, mais la validation en deux phases de PostgreSQL™ (PREPARE TRANSACTION(7) et COMMIT PREPARED(7)) autorise son intégration dans une application ou un middleware.
Parce que PostgreSQL™ est libre et facilement extensible, certaines sociétés utilisent PostgreSQL™ dans des solutions commerciales fermées (closed-source) proposant des fonctionnalités de bascule sur incident (failover), réplication et répartition de charge.
La Tableau 25.1, « Matrice de fonctionnalités : haute disponibilité, répartition de charge et réplication » résume les possibilités des différentes solutions listées plus-haut.
Tableau 25.1. Matrice de fonctionnalités : haute disponibilité, répartition de charge et réplication
Fonctionnalité | Bascule par disques partagés (Shared Disk Failover) | Réplication par système de fichiers | Envoi des journaux de transactions | Réplication maître/esclave basé sur les triggers | Middleware de réplication sur instructions | Réplication asynchrone multi-maîtres | Réplication synchrone multi-maîtres |
---|---|---|---|---|---|---|---|
Exemple d'implémentation | NAS | DRBD | Réplication en flux | Slony | pgpool-II | Bucardo | |
Méthode de communication | Disque partagé | Blocs disque | WAL | Lignes de tables | SQL | Lignes de tables | Lignes de tables et verrous de ligne |
Ne requiert aucun matériel spécial | • | • | • | • | • | • | |
Autorise plusieurs serveurs maîtres | • | • | • | ||||
Pas de surcharge sur le serveur maître | • | • | • | ||||
Pas d'attente entre serveurs | • | avec sync à off | • | • | |||
Pas de perte de données en cas de panne du maître | • | • | avec sync à on | • | • | ||
Les esclaves acceptent les requêtes en lecture seule | avec un Hot Standby | • | • | • | • | ||
Granularité de niveau table | • | • | • | ||||
Ne nécessite pas de résolution de conflit | • | • | • | • | • |
Certaines solutions n'entrent pas dans les catégories ci-dessus :
Le partitionnement des données divise les tables en ensembles de données. Chaque ensemble ne peut être modifié que par un seul serveur. Les données peuvent ainsi être partitionnées par bureau, Londres et Paris, par exemple, avec un serveur dans chaque bureau. Si certaines requêtes doivent combiner des données de Londres et Paris, il est possible d'utiliser une application qui requête les deux serveurs ou d'implanter une réplication maître/esclave pour conserver sur chaque serveur une copie en lecture seule des données de l'autre bureau.
La plupart des solutions ci-dessus permettent à plusieurs serveurs de répondre à des requêtes multiples, mais aucune ne permet à une seule requête d'être exécutée sur plusieurs serveurs pour se terminer plus rapidement. Cette solution autorisent plusieurs serveurs à travailler ensemble sur une seule requête. Ceci s'accomplit habituellement en répartissant les données entre les serveurs, chaque serveur exécutant une partie de la requête pour renvoyer les résultats à un serveur central qui les combine et les renvoie à l'utilisateur. Pgpool-II™ offre cette possibilité. Cela peut également être implanté en utilisant les outils PL/Proxy™.