Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
609 lines (511 sloc) 21.4 KB
<?xml version="1.0" encoding="UTF-8"?>
<!-- Dernière modification
le $Date$
par $Author$
révision $Revision$ -->
<sect1 id="addthings">
<title>Ajouter des objets à la réplication</title>
<indexterm><primary>ajouter des objets à la réplication</primary></indexterm>
<para>
Vous découvrirez peut-être que vous avez oubliez des choses que vous vouliez
répliquer.
</para>
<para>
En général, on peut très aisément y remédier. Cette section propose un
<quote>tour d'horizon</quote> des moyens pour répondre à la question
<quote>Comment réaliser la tache <emphasis>X</emphasis> avec
&slony1;&nbsp;?</quote>, pour différente valeur de <emphasis>X</emphasis>.
</para>
<para>
On ne peut pas utiliser directement les commandes <xref
linkend="stmtsetaddtable"/> ou <xref linkend="stmtsetaddsequence"/> de
<xref linkend="slonik"/> pour ajouter des tables et des séquences à un
ensemble de réplication en cours de fonctionnement&nbsp;; on doit au
contraire créer un nouvel ensemble de réplication. Une fois que ce nouvel
ensemble est répliqué à l'identique (c'est-à-dire les fournisseurs et
abonnés sont <emphasis>entièrement identiques</emphasis> à ceux de
l'ensemble que l'on veut compléter), les deux ensembles peuvent être
fusionnés avec la commande <xref linkend="stmtmergeset"/>.
</para>
<para>
Jusqu'à la version 1.0.2 (incluse), il existait des risques potentiels si
<xref linkend="stmtmergeset"/> était lancée alors que d'autres événements
de type abonnement étaient en attente&nbsp;; des confusions pouvaient se
produire sur les n&oelig;uds ayant ces événements en attente. Ce problème
fut résolu avec la version 1.0.5. Jusqu'à la version 1.2.1, il existait
toujours un problème avec <xref linkend="stmtmergeset"/> si la commande
était lancée avant que tous les abonnements soient complets, des
<quote>perturbations</quote> pouvaient apparaître sur les n&oelig;uds où
l'activité d'abonnement n'était pas terminée.
</para>
<para>
Notez que si vous ajoutez des n&oelig;uds, vous devez également ajouter les
déclarations <xref linkend="stmtstorepath"/> pour indiquer comment les
n&oelig;uds communiquent entre eux, et les déclarations <xref
linkend="stmtstorelisten"/> pour configurer le <quote>réseau de
communications</quote> correspondant. Voir le chapitre <xref
linkend="listenpaths"/> pour plus de détails.
</para>
<para>
Il est conseillé d'être très prudent lorsqu'on ajoute des n&oelig;uds et des
voies de communications. Par exemple, soumettre de multiples demandes
d'abonnements à un ensemble donné dans un script <xref linkend="slonik"/>
finit mal, en général. S'il est <emphasis>vraiment</emphasis> nécessaire
d'automatiser cette étape, il est préférable de soumettre des requêtes
<xref linkend="stmtwaitevent"/> entre chaque requête d'abonnement pour que
le script <xref linkend="slonik"/> attende qu'un abonnement soit complet
avant de lancer le suivant.
</para>
<para>
Mais en général, il est plus facile de gérer les reconfigurations complexes
en s'assurant qu'un changement a été parfaitement réussi avant de passer au
suivant. Il est beaucoup plus simple de corriger un problème unique que de
réparer les dégâts provoqués par l'interaction erronée de cinq commandes
successives.
</para>
<para>
Voici un ensemble de <quote>recettes</quote> pour réaliser différentes
modifications sur la configuration de la réplication.
</para>
<sect2>
<title>Ajouter une table dans le cluster de réplication</title>
<indexterm><primary>ajouter une table dans le cluster de réplication</primary></indexterm>
<para>
&slony1; ne vous permet pas d'ajouter une table dans un ensemble qui est déjà
en cours de réplication. En principe, c'est certainement
<emphasis>possible</emphasis>&nbsp;; mais cela implique que l'événement
SET_ADD_TABLE produise le code adéquat à partir de l'événement SUBSCRIBE_SET
invoqué pour analyser la table. Cela compliquerait de manière significative
et regrettable la logique de tous ces composants, donc ce n'est pas permis.
</para>
<para>
En contrepartie, vous devez procéder de la manière suivante&nbsp;:
</para>
<itemizedlist>
<listitem>
<para>Ajouter la nouvelle table sur chaque n&oelig;ud.</para>
<para>
En principe, le script <xref linkend="stmtddlscript"/> peut être utilisé
pour cela, mais en réalité cela provoque des <link
linkend="locking">problèmes d'inter-blocages</link> et cela nécessite la
modification de <emphasis>toutes</emphasis> les tables dans l'ensemble de
réplication existant, sur <emphasis>tous</emphasis> les n&oelig;uds, ce
qui fait que <xref linkend="stmtddlscript"/> est une approche peu
attrayante sur un serveur chargé. Ceci brise la règle de &slony1; qui dit
qu'<quote>il n'est pas nécessaire d'interrompre l'activité normale pour
ajouter la réplication</quote>.
</para>
<para>
À contrario, vous pouvez ajouter la table via <application>psql</application>
sur chaque n&oelig;ud.
</para>
</listitem>
<listitem>
<para>
Créer un nouvel ensemble de réplication avec <xref linkend="stmtcreateset"/>.
</para>
</listitem>
<listitem>
<para>
Ajouter la table dans le nouvel ensemble avec <xref
linkend="stmtsetaddtable"/>
</para>
</listitem>
<listitem>
<para>
Demander l'abonnement de ce nouvel ensemble avec <xref
linkend="stmtsubscribeset"/>. S'il existe plusieurs n&oelig;uds, vous
devez utiliser <xref linkend="stmtsubscribeset"/> une fois pour chaque
n&oelig;ud que vous voulez abonner.
</para>
</listitem>
<listitem>
<para>
Si vous voulez savoir de manière déterministe si un abonnement est
complet, vous devez soumettre pour chaque abonnement un script
slonik qui ressemble à cela&nbsp;:
<screen>SUBSCRIBE SET (ID=1, PROVIDER=1, RECEIVER=2);
WAIT FOR EVENT (ORIGIN=2, CONFIRMED = 1);
SYNC(ID = 1);
WAIT FOR EVENT (ORIGIN=1, CONFIRMED=2);</screen>
</para>
</listitem>
<listitem>
<para>
Une fois que les abonnements sont configurés de manière à ce que les
abonnements du nouvel ensemble soient identiques à ceux de l'ancien
ensemble, vous pouvez fusionner le nouveau et l'ancien avec la commande
<xref linkend="stmtmergeset"/>.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Comment ajouter une colonne dans une table répliquée</title>
<indexterm><primary>ajouter des colonnes dans une table</primary></indexterm>
<para>
Cette réponse est la même que pour la question <quote>Comment renommer des
colonnes dans une table répliquée&nbsp;?</quote>, et plus généralement aux
autres questions du type <quote>Comment modifier la définition de tables
répliquées&nbsp;?</quote>
</para>
<para>
Si vous changez la <quote>forme</quote> d'une table répliquée, vous devez le
faire au même instant dans le <quote>flux de transaction</quote> sur tous les
n&oelig;uds qui sont abonnés à l'ensemble qui contient la table.
</para>
<para>
Ainsi, la méthode consiste à construire un script SQL composé des changements
DDL et de le soumettre à tous les n&oelig;uds via la commande Slonik <xref
linkend="stmtddlscript"/>.
</para>
<para>
Il existe une alternative si vous avec installé les <link
linkend="altperl">scripts altperl</link>. Vous pouvez utiliser
<command>slonik_execute_script</command> pour cela&nbsp;:
</para>
<para>
<command>slonik_execute_script [options] numero_de_l_ensemble full_path_to_sql_script_file</command>
</para>
<para>
Tapez la commande <command>slonik_execute_script -h</command> pour plus
d'informations&nbsp;; notez que ce script utilise <xref
linkend="stmtddlscript"/>.
</para>
<para>
Il y a de nombreux <quote>points délicats</quote> à noter...
</para>
<itemizedlist>
<listitem>
<para>
Vous <emphasis>ne devez absolument jamais</emphasis> inclure des
commandes de contrôle de transaction, notamment <command>BEGIN</command>
et <command>COMMIT</command>, à l'intérieur de ces scripts. &slony1;
encapsule les scripts DDL avec une paire
<command>BEGIN</command>/<command>COMMIT</command>&nbsp;; ajouter des
opérateurs de contrôle de transaction supplémentaires implique que des
parties des ordres DDL seront <quote>validées</quote> en dehors du
contrôle de &slony1;.
</para>
</listitem>
<listitem>
<para>
Avant la version 1.2, il était nécessaire d'être extrêmement restrictif
sur ce qu'on envoyait au script <xref linkend="stmtddlscript"/>.
</para>
<para>
Il était interdit de placer du texte <command>entre guillemets
simples</command> dans le script car cela l'empêchait d'être stocké et
transmis correctement. À partir de la version 1.2, les guillemets simples
sont correctement prises en compte.
</para>
<para>
Si vous soumettez une séries d'ordre DDL, les derniers ne peuvent pas
faire référence aux objets créés par les premiers car tous les ordres
sont soumis dans une requête unique, dont le plan d'exécution est basé
sur l'état de la base de données au <emphasis>début</emphasis>, avant
que les modifications ne soient effectuées. À partir de la version 1.2,
il y a 12 ordres SQL, chacun est soumis individuellement ainsi la
commande <command>ALTER TABLE x ADD COLUMN c1 integer;</command> peut
désormais être suivie par <command>ALTER TABLE x ALTER COLUMN c1 SET NOT
NULL;</command>.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Comment supprimer la réplication sur un n&oelig;ud</title>
<para>
Vous devez supprimer les différents composants &slony1; connectés à la base.
</para>
<para>
Considérons, un instant, que nous faisons cela pour un n&oelig;ud. Si vous
avez de multiples n&oelig;uds, vous devrez répéter ces étapes autant de fois
que nécessaire.
</para>
<para>
Les composants à retirer&nbsp;:
</para>
<itemizedlist>
<listitem>
<para>Triggers de logs / Triggers de blocage de mises à jour</para>
</listitem>
<listitem>
<para>
Le schéma <quote>cluster</quote> contenant les tables &slony1; indiquant
l'état du n&oelig;ud et diverses procédures stockées
</para>
</listitem>
<listitem>
<para>
Le processus &lslon; qui gère le n&oelig;ud
</para>
</listitem>
<listitem>
<para>
Accessoirement, les scripts SQL, les scripts pl/pgsql et les binaires
&slony1; qui font partie de la compilation de &postgres;. (Bien sûr,
cela complique la tache si vous souhaitez redémarrer la réplication&nbsp;;
il est peu probable que vous ayez besoin de supprimer ces fichiers...)
</para>
</listitem>
</itemizedlist>
<para>Comment effectuer facilement la suppression</para>
<itemizedlist>
<listitem>
<para>
Vous pouvez utiliser la commande Slonik <xref linkend="stmtdropnode"/>
pour supprimer un n&oelig;ud du cluster. Ceci provoquera la suppression
des triggers et tout ce qui se trouve dans schéma cluster. Le processus
<xref linkend="slon"/> va mourir automatiquement.
</para>
</listitem>
<listitem>
<para>
Dans le cas d'un n&oelig;ud en échec (lorsque vous avez utilisé la
commande <xref linkend="stmtfailover"/> pour basculer sur un autre
n&oelig;ud), vous devrez peut-être utiliser <xref
linkend="stmtuninstallnode"/> pour supprimer les triggers, le schéma
et les fonctions.
</para>
<para>
Si le n&oelig;ud est en échec à cause d'une panne matérielle dramatique
(<emphasis>par exemple</emphasis> si vos disques ont pris feu), il est
possible qu'il n'y ait plus de traces de la base de données sur le
n&oelig;ud&nbsp;; en général, la base ne survit que lorsque la panne
matérielle est un problème de réseau qui n'endommage pas les données
mais qui vous oblige à supprimer le n&oelig;ud à cause de coupures réseau
persistantes.
</para>
</listitem>
<listitem>
<para>
Si les opérations ci-dessus se sont particulièrement mal passée, vous
pouvez lancer la commande SQL <command>DROP SCHEMA "Nom_du_cluster"
CASCADE;</command> qui supprime toutes les fonctions, les tables et
les triggers de &slony1;. En général, c'est une opération moins pratique
que <xref linkend="stmtuninstallnode"/> car cette commande ne se contente
pas de supprimer le schéma et son contenu, elle supprime également toutes
les colonnes ajoutées avec la commande <xref linkend= "stmttableaddkey"/>.
</para>
<note>
<para>
Dans &slony1; version 2.0, <xref linkend="stmttableaddkey"/>
<emphasis>n'est plus supporté</emphasis> et donc <xref
linkend="stmtuninstallnode"/> correspond simplement à <command>DROP
SCHEMA "nom_du_cluster" CASCADE;</command>.
</para>
</note>
</listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Ajouter un n&oelig;ud dans le cluster de réplication</title>
<para>
Les choses ne sont pas fondamentalement différentes entre l'ajout d'un
n&oelig;ud flambant neuf et la restauration d'un n&oelig;ud qu'on supprime
puis reconstruit. Dans les deux cas, vous ajoutez un n&oelig;ud dans le
cluster de réplication.
</para>
<para>
Les étapes nécessaires sont...
</para>
<itemizedlist>
<listitem>
<para>
Déterminer le numéro du n&oelig;ud et les DSN adéquats pour le n&oelig;ud.
Utilisez la commande &postgres; <command>createdb</command> pour créer la
base&nbsp;; ajoutez les définitions des tables que vous voulez répliquer
car &slony1; ne propage pas automatiquement cette information.
</para>
<para>
Si vous ne disposez pas d'un script SQL parfaitement propre pour ajouter
les tables, alors vous pouvez utiliser l'outil <link
linkend="extractschema"><command>slony1_extract_schema.sh</command></link>
situé dans le répertoire <filename>tools</filename> afin d'obtenir le
schéma utilisateur sans les <quote>morceaux</quote> de &slony1;.
</para>
</listitem>
<listitem>
<para>
Si le n&oelig;ud était un n&oelig;ud en échec, vous devez lancer la
commande <xref linkend="stmtdropnode"/> de <xref linkend="slonik"/>
afin de vous débarrasser de ses vestiges dans le cluster et de supprimer
le schéma que &slony1; a créé.
</para>
</listitem>
<listitem>
<para>
Lancer la commande <xref linkend="stmtstorenode"/> de slonik pour établir
le nouveau n&oelig;ud.
</para>
</listitem>
<listitem>
<para>
À cet instant, vous pouvez lancer le démon &lslon; sur le nouveau
n&oelig;ud. Il ne connaîtra rien des autres n&oelig;uds, donc les logs
de ce n&oelig;ud seront particulièrement calmes.
</para>
</listitem>
<listitem>
<para>
Lancer la commande slonik <xref linkend="stmtstorepath"/> pour indiquer
comment les processus <xref linkend="slon"/> doivent communiquer avec le
nouveau n&oelig;ud. Dans la version 1.1 et suivante, cette commande
génère automatiquement des lignes de la table des <link
linkend="listenpaths">voies d'écoute</link>. Dans les versions
précédentes, vous devez utiliser <xref linkend="stmtstorelisten"/> pour
les générer manuellement.
</para>
</listitem>
<listitem>
<para>
À cet instant, lancer le script &lteststate; est une excellente idée. Ce
script parcourt le cluster tout entier et pointe les anomalies qu'il
trouve. Il peut notamment identifier une grande variété de problèmes
de communication.
</para>
</listitem>
<listitem>
<para>
Lancer commande slonik <xref linkend="stmtsubscribeset"/> pour abonner le
n&oelig;ud à l'ensemble de réplication.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Comment remanier les abonnements&nbsp;?</title>
<para>
Par exemple, on souhaite que le n&oelig;ud 3 reçoive les données en
provenance du n&oelig;ud 1, alors qu'actuellement il reçoit les données du
n&oelig;ud 2.
</para>
<para>
Il ne s'agit pas d'un cas d'utilisation de la commande <xref
linkend="stmtmoveset"/> car on ne souhaite pas déplacer l'origine, mais
simplement remanier les abonnés.
</para>
<para>
Pour cela, on peut simplement soumettre des requêtes <xref
linkend="stmtsubscribeset"/> pour <emphasis>modifier</emphasis> les
abonnements. Ces abonnements ne seront pas redémarrés à partir de zéro, mais
simplement reconfigurés.
</para>
</sect2>
<sect2>
<title>Comment utiliser le <link linkend="logshipping">Log Shipping</link>&nbsp;?</title>
<para>
Cette question est largement débattue dans la section <link
linkend="logshipping">Log Shipping</link>...
</para>
</sect2>
<sect2>
<title>Comment savoir si la réplication fonctionne&nbsp;?</title>
<para>
La preuve ultime est le fait que les données ajoutées sur l'origine soient
présentes sur les abonnés. Il suffit <quote>simplement de lancer une
requête</quote> pour le savoir.
</para>
<para>
Cependant, il existe quelques autres méthode pour examiner l'état de la
réplication&nbsp;:
</para>
<itemizedlist>
<listitem>
<para>Regarder les logs des processus &lslon;.</para>
<para>
Ils ne vous diront pas grand chose, même à un niveau de débogage
élevé sur le n&oelig;ud origine. Au niveau 2 de débogage, vous devriez
voir sur les abonnés les événements SYNCs qui sont en cours de
traitement. À partir de la version 1.2, les informations sur le
traitement des SYNC incluent le nombre de tables traitées, ainsi que
le nombre de lignes insérées, supprimées et mises à jour.
</para>
</listitem>
<listitem>
<para>
Regarder dans la vue <command> sl_status </command> sur le n&oelig;ud
origine.
</para>
<para>
Cette vue indique quel est le retard des différents n&oelig;uds abonnés.
Cette information n'est pertinente que sur un n&oelig;ud origine.
</para>
</listitem>
<listitem>
<para>
Lancer le script &lteststate; qui se trouve dans le répertoire
<filename>tools</filename>. Ce script parcourt le cluster tout entier et
pointe les anomalies qu'il détecte, ainsi que des informations sur le
statut de chaque n&oelig;ud.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Comment mettre à jour la version de &slony1;&nbsp;?</title>
<para>
La réponse se trouve <link linkend="slonyupgrade">ici</link>.
</para>
</sect2>
<sect2>
<title>Que se passe-t-il lors d'une bascule d'urgence&nbsp;?</title>
<para>
Une partie de la réponse se trouve dans la section <xref linkend="failover"/>
mais il reste beaucoup de choses à écrire sur le sujet...
</para>
</sect2>
<sect2>
<title>Comment <quote>déplacer le maître</quote> vers un autre n&oelig;ud&nbsp;?</title>
<para>
Tout d'abord il faut choisir un n&oelig;ud qui est connecté à l'ancienne origine
(sinon il n'est pas évident de conserver les connexions lors du changement).
</para>
<para>
Deuxièmement, vous devez lancer un script &lslonik; avec la commande <xref
linkend="stmtlockset"/> pour verrouiller l'ensemble de réplication sur le
n&oelig;ud origine. Notez qu'à cet instant votre application risque de ne
plus fonctionner car cette opération pose des triggers sur l'origine qui
rejetent toutes les mises à jour.
</para>
<para>
Maintenant, lancez la requête &lslonik; <xref linkend="stmtmoveset"/>. Il est
parfaitement raisonnable de soumettre les deux requêtes à l'intérieur d'un
même script &lslonik;. Désormais, l'origine est basculée vers le nouveau
n&oelig;ud origine. Si le nouveau n&oelig;ud a quelques événement de retard,
il faudra un peu de temps pour que tout se mette en place.
</para>
</sect2>
<sect2>
<title>Comment réaliser une <quote>synchronisation complète</quote> sur une table&nbsp;?</title>
<para>
Pour &slony1;, la notion de <command>SYNC</command> est toujours quelque
chose d'<emphasis>incrémental</emphasis>&nbsp;; un <command>SYNC</command>
représente un ensemble de mises à jour qui furent <quote>validées</quote>
pendant la durée d'un événement <command>SYNC</command> donné sur le
n&oelig;ud origine. Si des mises à jour qui ont altéré l'ensemble du contenu
d'une table sont <quote>validées</quote> au cours d'un <command>SYNC</command>
unique, alors cela affectera l'ensemble du contenu de la table. Mais du point
de vue de &slony1;, ce changement est <quote>incrémental</quote> même si la
modification concerne <quote>la table toute entière</quote>.
</para>
<para>
La seule fois où &slony1; <quote>synchronise</quote> le contenu d'une table
est lors de la mise en place de l'abonnement. À ce moment-là, il utilise la
commande <command>COPY</command> pour rapatrier la totalité du contenu de la
table à partir du n&oelig;ud fournisseur.
</para>
<para>
Puisque les tables abonnées sont protégées contre les modifications réalisées
par un autre utilisateur que &slony1;, il est impossible (mis à part
d'horribles bogues) que les tables soient désynchronisées. Si c'est le cas,
alors il y a vraiment un gros problème dans &slony1;.
</para>
<para>
Si une corruption très grave se produit, la solution est de retirer la table
de la réplication, puis de créer un nouvel ensemble de réplication et de
l'ajouter à nouveau.
</para>
</sect2>
</sect1>