En définissant les nœuds, on a conçu l'architecture du cluster de réplication ; il est temps de déterminer quelles données doivent être copiées entre les nœuds. Les groupes de données qui sont copiés sont nommés « ensembles de réplication ».
Un ensemble de réplication comprend :
Les clefs des tables à répliquer qui n'ont pas de clef primaire possible ;
Les tables qui doivent être répliquées ;
Les séquences qui doivent être répliquées.
Slony-I™ a besoin d'une clef primaire ou d'un ensemble de champ éligible au statut de clef primaire pour chacune des tables qui seront répliquées. Les valeurs de clefs primaires (acronyme « PK ») sont utilisées comme identifiant primaire pour chaque ligne qui est modifiée sur le système source. Notons que les clefs primaires peuvent être des clefs composées de plusieurs colonnes NOT NULL ; elles ne doivent pas obligatoirement être constituées de champs uniques. Il y a trois façons de préciser à Slony-I™ quelle clef primaire utiliser :
Si la table a déjà une clef primaire identifiée, SLONIK SET ADD TABLE(7) peut être utilisé sans qu'il soit nécessaire de préciser la clef primaire. Slony-I™ peut automatiquement comprendre qu'il existe une clef primaire et l'utiliser.
Si la table ne dispose pas d'une clef primaire mais a une clef primaire candidate, c'est-à-dire un index sur une combinaison de champs qui sont à la fois UNIQUE et NOT NULL, alors vous pouvez spécifier cette clef comme ceci :
SET ADD TABLE (set id = 1, origin = 1, id = 42,
full qualified name = 'public.ma_table',
key = 'ma_table_idx',
comment='ma_table_idx est une clef primaire candidate de ma_table');
Cependant, une fois arrivé à cette étape, pourquoi ne pas déclarer l'index comme une clef primaire, ce qui nécessite que les colonnes impliquées soient NOT NULL, et ce qui constituera un index unique. Voici un exemple :
DROP INDEX ma_table_nom_col1_col2_uniq_idx; ALTER TABLE ma_table_nom ADD PRIMARY KEY (col1, col2);
Si votre application utilise l'index ma_table_nom, vous ne perdrez rien et cela vous donnera l'avantage d'avoir une clef primaire sur votre table.
Notons que si vous devez spécifier un espace de nom (« namespace ») pour la table, vous ne devez pas préciser l'espace de nom de la clef car cela peut interférer avec d'autres espaces de noms de la table.
Si la table n'a pas de clef primaire candidate, vous devez demander à Slony-I™ d'en produire une en utilisant la commande SLONIK TABLE ADD KEY(7).
La commande SLONIK TABLE ADD KEY(7) a toujours été considérée au mieux comme un « bricolage », et à partir de la version 2.0, elle est considérée comme une mauvaise fonctionnalité qu'il faut supprimer.
Il n'est pas terriblement important de sélectionner une « vraie » clef primaire ou une simple « clef primaire ». Cependant, il est fortement recommandé d'utiliser une de ces deux solutions plutôt que de laisser Slony-I™ remplir la colonne de clef primaire à votre place. Si vous n'avez pas de clef primaire candidate, cela signifie que la table ne fournit aucun mécanisme à votre application pour garder les lignes uniques. Dans ce cadre, Slony-I™ peut introduire des erreurs dans votre application. De plus, cela implique que vous pouvez entrer des données erronées dans la base de données.
Il est vital de regrouper les tables dans un seul ensemble lorsque ces tables sont reliées par une clef étrangère. Si des tables reliées de cette manière ne sont pas répliquées ensembles, vous rencontrerez des problèmes lors de la bascule du nœud « fournisseur maître » vers un autre nœud, et vous obtiendrez un nouveau « maître » qui ne peut pas être mis à jour correctement car le contenu de certaines tables n'est pas disponible.
Il y a également plusieurs raisons pour ne pas placer toutes les tables dans un ensemble unique :
Sur un ensemble très large, l'événement initial COPY_SET provoque de très longues transactions sur le nœud fournisseur. La FAQ décrit un certain nombre de problèmes qui conduisent à des transactions qui ralentissent les performances du système.
Si vous pouvez découper un grand ensemble en plusieurs plus petits ensembles, cela réduira la longueur de chaque transactions et diminuera leur impact négatif sur les performances.
Un autre problème survient fréquemment lorsque l'on réplique via un WAN ; parfois la connexion réseau est un peu instable, si bien qu'il y a des risques qu'une connexion reste ouverte pendant plusieurs heures et entraîne un CONNECTION TIMEOUT. Si cela se produit à 95% d'une copie d'un ensemble de réplication de 50 tables, représentant 250GB de données, cela va gâcher votre journée. Au contraire si les tables sont séparées en plusieurs ensembles de réplication, cette panne réseau qui intervient à 95% n'interrompra que la copie d'un seul ensemble.
Certains « effets négatifs » surviennent lorsque la base de données répliquée contient plusieurs Go de données, et qu'il faut des heures ou des jours pour qu'un nœud abonné réalise une copie complète des données initiales. Pour les bases relativement petites, cela n'est pas un facteur important.
Chaque invocation de la commande SLONIK EXECUTE SCRIPT(7) nécessite un verrou sur chaque table de l'ensemble de réplication, d'abord sur le nœud d'origine puis, avec la propagation de l'événement, sur chacun des nœuds abonnés .
Des retours d'expériences « de terrain » indiquent que cela peut conduire à des inter-blocages de verrous ("deadlocks"), ce qui nécessite d'appeler la requête SLONIK EXECUTE SCRIPT(7) plusieurs fois pour réussir à l'exécuter complètement.
Plus vous avez de tables dans un ensemble de réplication, plus ces tables doivent être verrouillées et plus les risques d'obtenir un inter-blocage des verrous sont importants.
Dans le même ordre d'idées, si un script DDL particulier doit simplement affecter deux tables, vous devez utiliser SLONIK SET MOVE TABLE(7) pour les déplacer temporairement dans un nouvel ensemble de réplication. En diminuant le nombre de verrous nécessaire, cela simplifiera la mise en place des changements DDL.
Il y a de plus amples discussions sur les verrous qui décrivent quand Slony-I™ a besoin de verrous et leur impact sur vos applications.
Chaque fois qu'un évènement SYNC est traité, les valeurs sont enregistrées pour toutes les séquences de l'ensemble de réplication. Si vous avez beaucoup de séquences, cela peut augmenter fortement la volumétrie de la table sl_seqlog.
Cela illustre une différence importante entre les tables et les séquences : si vous ajoutez des tables supplémentaire qui ont peu d'activité, voire aucune, cela n'ajoute pas de charge supplémentaire pour le système de réplication. Pour les séquences répliquées, les valeurs doivent être régulièrement propagées aux abonnés. Considérons les conséquences :
Une table répliquée mais qui n'est jamais mise à jour n'entraîne pas de travail supplémentaire.
Si elle n'est jamais mise à jour, le trigger de la table sur le nœud origine n'est jamais déclenché, et aucune entrée n'est ajoutée dans sl_log_1/sl_log_2. La table n'apparaît jamais dans aucune des requêtes de réplication (par exemple : dans les requêtes FETCH 100 FROM LOG utilisées pour trouver les données à répliquer) car elles ne recherchent que les tables qui ont des entrées dans sl_log_1/sl_log_2.
Au contraire, une certaine quantité de travail est ajoutée lors d'un événement SYNC pour chaque séquence qui est répliquée.
Pour répliquer 300 séquences, 300 lignes doivent être ajoutées dans la sl_seqlog de manière régulière, au moins jusqu'à la branche 2.0 où les mises à jour sont seulement appliquées quand la valeur d'une séquence données est visible modifiée.
Il est probable que si une valeur d'une séquence particulière n'a pas changé depuis la dernière vérification, alors il n'est peut-être pas nécessaire de stocker cette valeur encore et encore. Certaines reflexions sont en cours sur le moyen de réaliser cela de manière sécurisée.
Le bug #1226 indique une condition d'erreur qui peut se produire si vous avez un ensemble de réplication composé uniquement de séquences.
Ceci est documenté plus précisément dans la FAQ. En résumé, avoir un ensemble de réplication composé uniquement de séquences n'est pas particulièrement une bonne idée.