Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Comprendre les conflits actifs-actifs
Lorsque vous utilisez pgactive en mode actif-actif, l'écriture dans les mêmes tables à partir de plusieurs nœuds peut créer des conflits de données. Alors que certains systèmes de clustering utilisent des verrous distribués pour empêcher les accès simultanés, pgactive adopte une approche optimiste qui convient mieux aux applications distribuées géographiquement.
Certains systèmes de clustering de bases de données empêchent l'accès simultané aux données en utilisant des verrous distribués. Bien que cette approche fonctionne lorsque les serveurs sont à proximité, elle ne prend pas en charge les applications distribuées géographiquement car elle nécessite une latence extrêmement faible pour de bonnes performances. Au lieu d'utiliser des verrous distribués (approche pessimiste), l'extension pgactive utilise une approche optimiste. Cela signifie que :
-
Vous aide à éviter les conflits dans la mesure du possible.
-
Permet à certains types de conflits de se produire.
-
Permet de résoudre les conflits lorsque des conflits surviennent.
Cette approche vous donne plus de flexibilité lors de la création d'applications distribuées.
Comment se produisent les conflits
Les conflits entre nœuds proviennent de séquences d'événements qui ne pourraient pas se produire si toutes les transactions impliquées se produisaient simultanément sur le même nœud. Comme les nœuds n'échangent des modifications qu'une fois les transactions validées, chaque transaction est valide individuellement sur le nœud sur lequel elle a été validée, mais ne le serait pas si elle était exécutée sur un autre nœud ayant effectué un autre travail dans l'intervalle. Comme pgactive apply rejoue essentiellement la transaction sur les autres nœuds, l'opération de réexécution peut échouer en cas de conflit entre une transaction appliquée et une transaction validée sur le nœud récepteur.
La raison pour laquelle la plupart des conflits ne peuvent pas se produire lorsque toutes les transactions sont exécutées sur un seul nœud est que PostgreSQL dispose de mécanismes de communication entre transactions pour les empêcher, notamment :
-
Des index UNIQUES
-
SEQUENCEs
-
Verrouillage des lignes et des relations
-
Suivi des dépendances SÉRIALISABLE
Tous ces mécanismes sont des moyens de communiquer entre les transactions afin d'éviter les problèmes de simultanéité indésirables.
pgactive atteint une faible latence et gère bien les partitions réseau car il n'utilise pas de gestionnaire de transactions distribué ni de gestionnaire de verrouillage. Cependant, cela signifie que les transactions sur différents nœuds s'exécutent de manière totalement isolée les unes des autres. Bien que l'isolation améliore généralement la cohérence de la base de données, dans ce cas, vous devez réduire l'isolation pour éviter les conflits.
Types de conflits
Les conflits qui peuvent survenir incluent :
Rubriques
Conflits de clé primaire ou unique
Les conflits de lignes se produisent lorsque plusieurs opérations tentent de modifier la même clé de ligne d'une manière impossible sur un seul nœud. Ces conflits constituent le type de conflit de données le plus courant.
pgactive résout les conflits détectés par le biais de last-update-wins la gestion ou de votre gestionnaire de conflits personnalisé.
Les conflits de lignes incluent :
-
INSÉRER ou INSÉRER
-
INSÉRER ou METTRE À JOUR
-
METTRE À JOUR ou SUPPRIMER
-
INSÉRER ou SUPPRIMER
-
SUPPRIMER ou SUPPRIMER
-
INSÉRER ou SUPPRIMER
Conflits entre INSERTION ET INSERTION
Ce conflit le plus courant se produit lorsque, INSERTs sur deux nœuds différents, créez un tuple avec les mêmes valeurs de CLÉ PRIMAIRE (ou des valeurs de contrainte UNIQUE identiques lorsqu'aucune CLÉ PRIMAIRE n'existe).
pgactivelink résout les conflits INSERT en utilisant l'horodatage de l'hôte d'origine pour conserver le tuple le plus récent. Vous pouvez remplacer ce comportement par défaut à l'aide de votre gestionnaire de conflits personnalisé. Bien que ce processus ne nécessite aucune action particulière de l'administrateur, sachez que pgactivelink ignore l'une des opérations INSERT sur tous les nœuds. Aucune fusion automatique de données ne se produit à moins que votre gestionnaire personnalisé ne l'implémente.
Le pgactivelink ne peut résoudre que les conflits impliquant une seule violation de contrainte. Si un INSERT enfreint plusieurs contraintes UNIQUE, vous devez mettre en œuvre des stratégies de résolution de conflits supplémentaires.
INSERTsqui violent plusieurs contraintes UNIQUES
Un conflit INSERT/INSERT peut violer plusieurs contraintes UNIQUE, y compris la CLÉ PRIMAIRE. pgactivelink ne peut gérer que les conflits impliquant une seule contrainte UNIQUE. Lorsque les conflits violent plusieurs contraintes UNIQUE, le programme d'application échoue et renvoie le message d'erreur suivant :
multiple unique constraints violated by remotely INSERTed tuple.
Dans les anciennes versions, cette situation générait plutôt une erreur de « conflit d'unicité divergente ».
Pour résoudre ces conflits, vous devez effectuer une action manuelle. SUPPRIMEZ les tuples locaux en conflit ou METTEZ-les à jour pour supprimer les conflits avec le nouveau tuple distant. Sachez que vous devrez peut-être résoudre plusieurs tuples en conflit. À l'heure actuelle, pgactivelink ne fournit aucune fonctionnalité intégrée permettant d'ignorer, de supprimer ou de fusionner les tuples qui violent plusieurs contraintes uniques.
Note
Pour plus d'informations, consultez la section UPDATEs relative à la violation de plusieurs contraintes UNIQUE.
Conflits de mise à jour/mise à jour
Ce conflit se produit lorsque deux nœuds modifient simultanément le même tuple sans changer sa CLÉ PRIMAIRE. pgactivelink résout ces conflits en utilisant la last-update-wins logique ou votre gestionnaire de conflits personnalisé, s'il est défini. Une CLÉ PRIMAIRE est essentielle pour l'appariement des tuples et la résolution des conflits. Pour les tables sans CLÉ PRIMAIRE, pgactivelink rejette les opérations UPDATE avec l'erreur suivante :
Cannot run UPDATE or DELETE on table (tablename) because it does not have a
primary key.
METTRE À JOUR les conflits sur la CLÉ PRIMAIRE
pgactive a des limites lors de la gestion des mises à jour de PRIMARY KEY. Bien que vous puissiez effectuer une opération de mise à jour sur une CLÉ PRIMAIRE, pgactive ne peut pas résoudre automatiquement les conflits en utilisant last-update-wins la logique de ces opérations. Vous devez vous assurer que les mises à jour de votre CLÉ PRIMAIRE n'entrent pas en conflit avec les valeurs existantes. Si des conflits surviennent lors des mises à jour de la CLÉ PRIMAIRE, ils deviennent des conflits divergents qui nécessitent une intervention manuelle de votre part. Pour plus d'informations sur la gestion de ces situations, consultezConflits divergents.
UPDATEsqui violent plusieurs contraintes UNIQUES
pgactivelink ne peut pas appliquer de résolution de last-update-wins conflit lorsqu'une mise à jour entrante viole plusieurs contraintes UNIQUES ou valeurs PRIMARY KEY. Ce comportement est similaire à celui des opérations INSERT comportant plusieurs violations de contraintes. Ces situations créent des conflits divergents qui nécessitent une intervention manuelle de votre part. Pour de plus amples informations, veuillez consulter Conflits divergents.
Conflits de mise à jour/suppression
Ces conflits se produisent lorsqu'un nœud UPDATEs par ligne et qu'un autre nœud le DELETEs fait simultanément. Dans ce cas, un conflit UPDATE/DELETE se produit lors de la rediffusion. La solution consiste à ignorer toute mise à jour qui arrive après un DELETE, sauf indication contraire de votre gestionnaire de conflits personnalisé.
pgactivelink a besoin d'une CLÉ PRIMAIRE pour faire correspondre les tuples et résoudre les conflits. Pour les tables dépourvues de CLÉ PRIMAIRE, il rejette les opérations DELETE avec l'erreur suivante :
Cannot run UPDATE or DELETE on table (tablename) because it does not have a
primary key.
Note
pgactivelink ne peut pas faire la distinction entre les conflits. UPDATE/DELETE and INSERT/UPDATE Dans les deux cas, une mise à jour affecte une ligne inexistante. En raison de la réplication asynchrone et de l'absence d'ordre de réexécution entre les nœuds, pgactivelink ne peut pas déterminer si la mise à jour concerne une nouvelle ligne (INSERT non encore reçu) ou une ligne supprimée. Dans les deux scénarios, pgactivelink ignore la mise à jour.
Conflits d'INSERTION ET DE MISE
Ce conflit peut se produire dans des environnements à nœuds multiples. Cela se produit lorsqu' INSERTs un nœud par ligne, un deuxième nœud UPDATEs et un troisième nœud reçoivent la mise à jour avant l'INSERT d'origine. Par défaut, pgactivelink résout ces conflits en supprimant la mise à jour, sauf indication contraire de votre déclencheur de conflit personnalisé. Sachez que cette méthode de résolution peut entraîner des incohérences de données entre les nœuds. Pour plus d'informations sur des scénarios similaires et leur gestion, consultezConflits de mise à jour/suppression.
Conflits SUPPRIMER/SUPPRIMER
Ce conflit se produit lorsque deux nœuds différents suppriment simultanément le même tuple. pgactivelink considère que ces conflits sont inoffensifs car les deux opérations DELETE ont le même résultat final. Dans ce scénario, pgactivelink ignore en toute sécurité l'une des opérations DELETE sans affecter la cohérence des données.
Conflits de contraintes de clé étrangère
Les contraintes FOREIGN KEY peuvent provoquer des conflits lors de l'application de transactions distantes à des données locales existantes. Ces conflits se produisent généralement lorsque les transactions sont appliquées dans un ordre différent de leur ordre logique sur les nœuds d'origine.
Par défaut, pgactive applique les modifications avec session_replication_role asreplica
, ce qui permet de contourner les vérifications par clé étrangère lors de la réplication. Dans les configurations active-active, cela peut entraîner des violations de clés étrangères. La plupart des violations sont temporaires et sont résolues une fois que la réplication a été rattrapée. Cependant, des clés étrangères peuvent se produire parce que pgactive ne prend pas en charge le verrouillage des lignes entre nœuds.
Ce comportement est inhérent aux systèmes actifs-actifs asynchrones tolérants aux partitions. Par exemple, le nœud A peut insérer une nouvelle ligne enfant tandis que le nœud B supprime simultanément sa ligne parent. Le système ne peut pas empêcher ce type de modification simultanée entre les nœuds.
Pour minimiser les conflits de clés étrangères, nous recommandons ce qui suit :
-
Limitez les relations de clé étrangère aux entités étroitement liées.
-
Modifiez les entités associées à partir d'un seul nœud lorsque cela est possible.
-
Choisissez des entités qui nécessitent rarement des modifications.
-
Mettez en œuvre un contrôle de simultanéité au niveau de l'application pour les modifications.
Conflits de contraintes d'exclusion
pgactive link ne supporte pas les contraintes d'exclusion et restreint leur création.
Note
Si vous convertissez une base de données autonome existante en base de données pgactivelink, supprimez manuellement toutes les contraintes d'exclusion.
Dans un système asynchrone distribué, il n'est pas possible de garantir qu'aucun ensemble de lignes ne viole la contrainte. Cela est dû au fait que toutes les transactions sur les différents nœuds sont totalement isolées. Les contraintes d'exclusion peuvent entraîner des blocages de rediffusion, dans lesquels la rediffusion ne peut pas progresser d'un nœud à l'autre en raison de violations des contraintes d'exclusion.
Si vous forcez pgactive Link à créer une contrainte d'exclusion, ou si vous ne supprimez pas les contraintes existantes lors de la conversion d'une base de données autonome en pgactive Link, la réplication risque de s'interrompre. Pour rétablir la progression de la réplication, supprimez ou modifiez les tuples locaux qui entrent en conflit avec un tuple distant entrant afin que la transaction distante puisse être appliquée.
Conflits de données mondiaux
Lorsque vous utilisez pgactivelink, des conflits peuvent survenir lorsque les nœuds possèdent des données globales PostgreSQL différentes à l'échelle du système, telles que des rôles. Ces conflits peuvent entraîner la réussite et la validation d'opérations (principalement DDL) sur un nœud, mais ne pas s'appliquer aux autres nœuds.
Si un utilisateur existe sur un nœud mais pas sur un autre, des problèmes de réplication peuvent survenir :
-
Node1 a un nom d'utilisateur
fred
, mais cet utilisateur n'existe pas sur Node2 -
Lors de
fred
la création d'une table sur Node1, la table est répliquéefred
en tant que propriétaire -
Lorsque cette commande DDL est appliquée à Node2, elle échoue car l'utilisateur
fred
n'existe pas -
Cet échec génère une erreur dans les journaux PostgreSQL sur Node2 et incrémente le compteur
pgactive.pgactive_stats.nr_rollbacks
Résolution : créez l'utilisateur fred
sur Node2. L'utilisateur n'a pas besoin d'autorisations identiques mais doit exister sur les deux nœuds.
Si une table existe sur un nœud mais pas sur un autre, les opérations de modification des données échoueront :
-
Node1 possède une table nommée
foo
qui n'existe pas sur Node2 -
Toute opération DML sur la
foo
table du Node1 échouera une fois répliquée sur Node2
Résolution : créez la table foo
sur Node2 avec la même structure.
Note
pgactivelink ne réplique actuellement pas les commandes CREATE USER ni les opérations DDL. La réplication DDL est prévue pour une future version.
Conflits de verrouillage et abandons les blocages
Comme les processus pgactive apply fonctionnent comme des sessions utilisateur normales, ils suivent les règles standard de verrouillage des lignes et des tables. Cela peut amener les processus d'application de pgactivelink à attendre les verrous détenus par les transactions des utilisateurs ou par d'autres processus d'application.
Les types de verrous suivants peuvent affecter les processus d'application :
-
Verrouillage explicite au niveau de la table (LOCK TABLE...) par les sessions utilisateur
-
Verrouillage explicite au niveau des lignes (SELECT... (POUR LA MISE À JOUR/POUR LE PARTAGE) par sessions utilisateur
-
Verrouillage à partir de clés étrangères
-
Verrouillage implicite dû à une ligne UPDATEs INSERTs DELETEs, ou à une activité locale ou à une application depuis d'autres serveurs
Des blocages peuvent survenir entre :
-
Un processus d'application pgactivelink et une transaction utilisateur
-
Deux processus d'application
Lorsque des blocages se produisent, le détecteur de blocage de PostgreSQL met fin à l'une des transactions problématiques. Si le processus du worker d'application pgactivelink est arrêté, il réessaie automatiquement et réussit généralement.
Note
-
Ces problèmes sont temporaires et ne nécessitent généralement pas l'intervention de l'administrateur. Si un processus d'application est bloqué pendant une période prolongée par le verrouillage d'une session utilisateur inactive, vous pouvez mettre fin à la session utilisateur pour reprendre la réplication. Cette situation est similaire à celle où un utilisateur détient un long verrou qui affecte une autre session utilisateur.
-
Pour identifier les délais de rediffusion liés au verrouillage, activez cette fonctionnalité
log_lock_waits
dans PostgreSQL.
Conflits divergents
Des conflits divergents se produisent lorsque des données qui devraient être identiques entre les nœuds diffèrent de façon inattendue. Bien que ces conflits ne devraient pas se produire, ils ne peuvent pas tous être évités de manière fiable dans le cadre de la mise en œuvre actuelle.
Note
La modification de la CLÉ PRIMAIRE d'une ligne peut provoquer des conflits divergents si un autre nœud modifie la clé de la même ligne avant que tous les nœuds n'aient traité la modification. Évitez de modifier les clés primaires ou limitez les modifications à un nœud désigné. Pour de plus amples informations, veuillez consulter METTRE À JOUR les conflits sur la CLÉ PRIMAIRE .
Les conflits divergents impliquant des données de ligne nécessitent généralement l'intervention de l'administrateur. Pour résoudre ces conflits, vous devez ajuster manuellement les données d'un nœud pour qu'elles correspondent à celles d'un autre tout en désactivant temporairement la réplication à l'aide pgactive.pgactive_do_not_replicate
de. Ces conflits ne devraient pas se produire lorsque vous utilisez pgactive comme indiqué et que vous évitez les paramètres ou les fonctions marqués comme dangereux.
En tant qu'administrateur, vous devez résoudre ces conflits manuellement. Selon le type de conflit, vous devrez utiliser des options avancées telles quepgactive.pgactive_do_not_replicate
. Utilisez ces options avec prudence, car une mauvaise utilisation peut aggraver la situation. En raison de la variété des conflits possibles, nous ne pouvons pas fournir d'instructions de résolution universelles.
Des conflits divergents se produisent lorsque des données qui devraient être identiques sur différents nœuds diffèrent de façon inattendue. Bien que ces conflits ne devraient pas se produire, ils ne peuvent pas tous être évités de manière fiable dans le cadre de la mise en œuvre actuelle.
Éviter ou tolérer les conflits
Dans la plupart des cas, vous pouvez utiliser une conception d'application appropriée pour éviter les conflits ou faire en sorte que votre application tolère les conflits.
Les conflits se produisent uniquement lorsque des opérations simultanées ont lieu sur plusieurs nœuds. Pour éviter les conflits :
-
Écrire sur un seul nœud
-
Écrire dans des sous-ensembles de base de données indépendants sur chaque nœud (par exemple, attribuer à chaque nœud un schéma distinct)
Pour les conflits INSERT et INSERT, utilisez des séquences globales pour éviter complètement les conflits.
Si les conflits ne sont pas acceptables pour votre cas d'utilisation, envisagez d'implémenter le verrouillage distribué au niveau de l'application. Souvent, la meilleure approche consiste à concevoir votre application pour qu'elle fonctionne avec les mécanismes de résolution de conflits de pgactive plutôt que d'essayer de prévenir tous les conflits. Pour de plus amples informations, veuillez consulter Types de conflits.
Enregistrement des conflits
pgactivelink enregistre les incidents de conflit dans le pgactive.pgactive_conflict_history
tableau pour vous aider à diagnostiquer et à gérer les conflits actifs-actifs. L'enregistrement des conflits dans cette table ne se produit que lorsque vous définissez pgactive.log_conflicts_to_table
le paramètre sur true. L'extension pgactive enregistre également les conflits dans le fichier journal de PostgreSQL lorsque log_min_messages est défini sur ou, quel que soit le paramètre. LOG
lower
pgactive.log_conflicts_to_table
Utilisez le tableau de l'historique des conflits pour :
-
Mesurez la fréquence à laquelle votre application crée des conflits
-
Identifiez les endroits où les conflits se produisent
-
Améliorez votre application pour réduire les taux de conflit
-
Détectez les cas où la résolution des conflits ne produit pas les résultats souhaités
-
Déterminez les domaines dans lesquels vous avez besoin de déclencheurs de conflits définis par l'utilisateur ou de modifications de conception d'applications
Pour les conflits de lignes, vous pouvez éventuellement enregistrer les valeurs des lignes. Ceci est contrôlé par le pgactive.log_conflicts_to_table
réglage. Remarque :
-
Il s'agit d'une option globale à l'échelle de la base de données
-
Il n'existe aucun contrôle par table sur la journalisation des valeurs des lignes
-
Aucune limite n'est appliquée aux numéros de champs, aux éléments du tableau ou à la longueur des champs
-
L'activation de cette fonctionnalité peut être déconseillée si vous travaillez avec des lignes de plusieurs mégaoctets susceptibles de déclencher des conflits
Étant donné que la table d'historique des conflits contient les données de chaque table de la base de données (chacune avec des schémas potentiellement différents), les valeurs des lignes enregistrées sont stockées sous forme de champs JSON. Le JSON est créé en utilisantrow_to_json
, comme si vous l'appeliez directement depuis SQL. PostgreSQL ne fournit pas de fonction, vous aurez donc besoin json_to_row
d'un code spécifique à la table (PL/pgSQL, PL/Python, PL/Perlin, etc.) pour reconstruire un tuple de type composite à partir du JSON enregistré.
Note
Support des conflits définis par l'utilisateur dans le cadre d'une future fonctionnalité d'extension.