Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
770 lines (651 sloc) 23.7 KB
<?xml version="1.0" encoding="UTF-8"?>
<!-- Dernière modification
le $Date$
par $Author$
révision $Revision$ -->
<sect1 id="versionupgrade">
<title>Utiliser &slony1; pour les mises à jour &postgres;</title>
<indexterm><primary>Mettre à jour la version de &postgres; en utilisant &slony1;</primary></indexterm>
<para>
Un certain nombre de personnes ont trouvé que &slony1; était pratique pour
effectuer les mises à jours de versions majeures (<emphasis>par
exemple</emphasis> celles qui nécessitent d'éxécuter
<application>initdb</application> afin de recréer une nouvelle instance)
sans subir une coupure de service importante.
</para>
<para>
La méthode simple que l'on peut imaginer pour effectuer une telle mise à jour
consiste à exécuter <application>pg_dump</application> sur l'ancienne version
de la base, puis d'envoyer le résultat dans une session
<application>psql</application> connectée à la nouvelle version de la base.
Malheureusement, le temps nécessaire pour cette approche peut être prohibitif.
Pour une base contenant 40&nbsp;Go de données ainsi que de nombreux index, le
processus nécessite les étapes suivantes&nbsp;:
<itemizedlist>
<listitem>
<para>
Arrêtez toutes les applications qui peuvent modifier les données&nbsp;;
</para>
</listitem>
<listitem>
<para>
Lancez <application>pg_dump</application> et chargez les données dans
la nouvelle base&nbsp;;
</para>
</listitem>
<listitem>
<para>
Attendez 40 heures que le processus d'extraction/chargement se
termine&nbsp;;
</para>
</listitem>
<listitem>
<para>
Faites pointer les applications <quote>en écriture</quote> vers la
nouvelle base.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Notez que cette approche a provoqué une coupure de service de 40 heures.
</para>
<para>
&slony1; offre une opportunité de remplacer cette longue coupure de service
par une autre de quelques secondes au minimum. L'approche requise
consiste à créer un réplicat &slony1; utilisant la nouvelle version de
&postgres;. Il est possible que cela prenne bien plus de 40 heures pour
créer ce réplicat. Néanmoins sa création ne nécessite aucun arrêt de
production et, une fois qu'il est créé, il peut être rafraîchi rapidement.
</para>
<para>
Au moment de basculer vers la nouvelle base de données, la portion de
procédure qui requiert un arrêt de production est beaucoup moins
longue&nbsp;:
<itemizedlist>
<listitem>
<para>
Arrêtez toutes les applications qui peuvent modifier les
données&nbsp;;
</para>
</listitem>
<listitem>
<para>
Verrouillez l'ensemble contre les lectures des applications clientes en
utilisant <xref linkend="stmtlockset"/>&nbsp;;
</para>
</listitem>
<listitem>
<para>
Lancez le commande Slonik <xref linkend="stmtmoveset"/> pour déplacer
l'origine de l'ensemble de réplication depuis l'ancienne base vers la
nouvelle&nbsp;;
</para>
</listitem>
<listitem>
<para>
Faites pointer les applications vers la nouvelle base.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Cette procédure devrait prendre très peu de temps, principalement le temps
nécessaire à la reconfiguration de vos applications. Si vous pouvez
automatiser toutes ces étapes, le temps hors production devrait être d'une
seconde, voire moins. Si la gestion manuelle est nécessaire, cela prendra
entre quelques secondes et quelques minutes.
</para>
<para>
Notez qu'après le déplacement de l'origine, les mises à jour vont vers
l'<emphasis>ancienne</emphasis> base. Si vous découvrez qu'à cause d'un
problème imprévu ou non testé, votre application rencontre certains problèmes
pour se connecter à la nouvelle base, vous pouvez facilement utiliser
<xref linkend="stmtmoveset"/> à nouveau pour déplacer de nouveau l'origine
vers l'ancienne base.
</para>
<para>
Si vous considérez qu'il est particulièrement vital de pouvoir revenir à
l'ancienne base dans l'état où elle se trouvait avant la bascule, afin de
pouvoir revenir complètement en arrière et que vous souhaitez également
pouvoir revenir à l'ancienne version (mise à jour depuis la bascule),
accomplissez les étapes suivantes&nbsp;:
<itemizedlist>
<listitem>
<para>
Préparez <emphasis> deux </emphasis> réplicats &slony1; de la base&nbsp;:
<itemizedlist>
<listitem>
<para>Un pour la nouvelle version de &postgres;&nbsp;;</para>
</listitem>
<listitem>
<para>Un pour l'ancienne version de &postgres;.</para>
</listitem>
</itemizedlist>
</para>
<para>
Ainsi, vous avez <emphasis>trois</emphasis> n&oelig;uds, un avec la
nouvelle version de &postgres;, et deux autres avec l'ancienne version.
</para>
<para>
Notez que ceci impose d'avoir une construction de &slony1; pour toutes les
bases de données <emphasis>à la fois</emphasis> (<emphasis>c'est-à-dire</emphasis>
à tout le moins, les binaires pour les procédures stockées doivent avoir
été compilés avec les différentes versions de &postgres;).
</para>
</listitem>
<listitem>
<para>
Une fois qu'ils sont à peu près <quote>synchronisés</quote>, arrêtez
toutes les applications qui peuvent modifier les données.
</para>
</listitem>
<listitem>
<para>
Lancez la synchronisation des n&oelig;uds, puis
<command>arrêtez</command> le démon <application>slon</application>
qui a synchronisé le n&oelig;ud esclave qui héberge l'ancienne version
de &postgres;.
</para>
<para>
Vous voudrez peut-être utiliser <xref linkend="stmtuninstallnode"/>
pour isoler ce n&oelig;ud et ainsi le transformer en une base
indépendante, ou simplement tuer le démon
<application>slon</application>, selon votre volonté de rendre cette
transformation permanente ou non.
</para>
</listitem>
<listitem>
<para>
Ensuite utilisez <xref linkend="stmtmoveset"/> pour déplacer l'origine,
comme décrit précédemment.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Si de <quote>petits</quote> problèmes apparaissent, vous pourrez récupérer
le n&oelig;ud qui héberge l'ancienne base qui a reçu les mises à jours de
données. Si vous découvrez des problèmes plus importants, vous pouvez
abandonner les deux n&oelig;uds et revenir à la base qui a été isolée.
</para>
<para>
Il ne s'agit pas ici de dire qu'il est courant de rencontrer des problèmes
qui nécessitent une procédure aussi <quote>paranoïaque</quote>. Toutefois,
les personnes soucieuses d'évaluer les risques peuvent être rassurées par de
tels choix.
</para>
<note>
<para>
&slony1; ne supporte pas les versions de &postgres; antérieures à la 7.3.3
parce qu'il a besoin des espaces de noms («&nbsp;namespaces&nbsp;») qui
n'étaient pas stables jusque là. Rod Taylor modifia une version de &slony1;
pour qu'elle fonctionne avec la 7.2 en autorisant les objets &slony1; à se
placer dans le schéma global. Il trouva cela assez compliqué. De plus,
certaines requêtes n'étaient pas assez rapides (l'optimiseur de requêtes de
&postgres; a été <emphasis>considérablement</emphasis> amélioré depuis la
version 7.2), cependant cette solution était plus pratique pour lui que
les autres systèmes de réplication tels que
<productname>eRServer</productname>. &postgres; 7.2 ne sera
<emphasis>jamais</emphasis> supportée par une version officielle de
&slony1;.
</para>
</note>
<sect2>
<title>Exemple&nbsp;: mise à jour d'une base simple sans réplication
existante</title>
<para>
Cet exemple montre noms, adresses IP, numéros de port, etc pour décrire en
détails ce qui se passe.
</para>
<sect3>
<title>L'environnement</title>
<programlisting>
Database machine:
nom = rome
ip = 192.168.1.23
OS: Ubuntu 6.06 LTS
utilisateur postgres = postgres, groupe postgres
Version actuelle de PostgreSQL
Version = 8.2.3
Port 5432
Installé sur : /data/pgsql-8.2.3
Répertoire des données : /data/pgsql-8.2.3/data
Base de données à déplacer : mydb
Nouvelle installation de PostgreSQL
Version = 8.3.3
Port 5433
Installé sur : /data/pgsql-8.3.3
Répertoire des données : /data/pgsql-8.3.3/data
Version Slony à utiliser = 1.2.14
</programlisting>
</sect3>
<sect3>
<title>Installer &slony1;</title>
<para>
L'installation de &slony1; est couverte assez bien dans les autres parties
de la documentation (<xref linkend="installation"/>)&nbsp;; nous allons
seulement fournir un guide rapide ici.
</para>
<programlisting>
wget http://main.slony.info/downloads/1.2/source/slony1-1.2.14.tar.bz2
</programlisting>
<para>
Déballez l'archive et construisez le paquet en tant que root avec&nbsp;:
</para>
<programlisting>
tar xjf slony1-1.2.14.tar.bz2
cd slony1-1.2.14
./configure --prefix=/data/pgsql-8.2.3 --with-perltools=/data/pgsql-8.2.3/slony --with-pgconfigdir=/data/pgsql-8.2.3/bin
make clean
make
make install
chown -R postgres:postgres /data/pgsq-8.2.3
mkdir /var/log/slony
chown -R postgres:postgres /var/log/slony
</programlisting>
<para>
Puis répétez ceci pour la construction de PostgreSQL 8.3.3. <command>make
clean</command> est une étape très importante&nbsp;; ce n'est pas si important
la première fois mais lors de la deuxième construction, il est essentiel de
supprimer les anciens binaires, sinon les binaires ne vont pas correspondre
à la construction 8.3.3 de &postgres; 8.3.3 avec comme résultat le non
fonctionnement de &slony1;.
</para>
</sect3>
<sect3>
<title>Créer slon_tools.conf</title>
<para>
slon_tools.conf est <emphasis>le</emphasis> fichier de configuration. Il
contient entre autres&nbsp;:
<orderedlist>
<listitem>
<para>
Tous les n&oelig;uds et leurs détails (IP, port, base de données,
utilisateur, mot de passe)&nbsp;;
</para>
</listitem>
<listitem>
<para>
Toutes les tables à répliquer&nbsp;;
</para>
</listitem>
<listitem>
<para>
Toutes les séquences à répliquer&nbsp;;
</para>
</listitem>
<listitem>
<para>
L'arrangement des tables et séquences en ensembles.
</para>
</listitem>
</orderedlist>
</para>
<para>
Faites une copie de
<filename>/data/pgsql-8.2.3/etc/slon_tools.conf-sample</filename> dans
<filename>slon_tools.conf</filename> et ouvrez ce dernier. Les commentaires
dans ce fichier sont suffisamment explicatifs. Comme il s'agit d'une
réplication en un temps, vous n'aurez généralement pas besoin de créer
plusieurs ensembles. Sur une machine de production comprenant 500 tables et
100 séquences, les placer dans un seul ensemble a bien fonctionné.
</para>
<para>
Quelques modifications à entreprendre&nbsp;:
</para>
<orderedlist>
<listitem>
<para>
Dans notre cas, nous avons seulement besoin de deux n&oelig;uds, donc
supprimez les <command>add_node</command> pour 3 et 4.
</para>
</listitem>
<listitem>
<para>
L'entrée <envar>pkeyedtables</envar> doit être mise à jour avec chacune de
vos tables qui ont une clé primaire. Si vos tables sont dans différents
schémas, vous devez qualifier le nom de la table avec celui du schéma
(nomschéma.nomtable).
</para>
</listitem>
<listitem>
<para>
L'entrée <envar>keyedtables</envar> doit être mise à jour avec toute
table correspondant au commentaire (si la conception du schéma est bonne,
il ne devrait pas y en avoir).
</para>
</listitem>
<listitem>
<para>
<envar>serialtables</envar> (si vous en avez, mais il est préférable de
les éviter).
</para>
</listitem>
<listitem>
<para>
<envar>sequences</envar> doit être mise à jour avec la liste de vos
séquences.
</para>
</listitem>
<listitem>
<para>
Supprimez complètement l'entrée set2 (car nous allons seulement utilisé
set1).
</para>
</listitem>
</orderedlist>
<para>
Voici à quoi cela ressemble une fois tous les commentaires supprimés&nbsp;:
<programlisting>
$CLUSTER_NAME = 'replication';
$LOGDIR = '/var/log/slony';
$MASTERNODE = 1;
add_node(node => 1,
host => 'rome',
dbname => 'mydb',
port => 5432,
user => 'postgres',
password => '');
add_node(node => 2,
host => 'rome',
dbname => 'mydb',
port => 5433,
user => 'postgres',
password => '');
$SLONY_SETS = {
"set1" => {
"set_id" => 1,
"table_id" => 1,
"sequence_id" => 1,
"pkeyedtables" => [
'mytable1',
'mytable2',
'otherschema.mytable3',
'otherschema.mytable4',
'otherschema.mytable5',
'mytable6',
'mytable7',
'mytable8',
],
"sequences" => [
'mytable1_sequence1',
'mytable1_sequence2',
'otherschema.mytable3_sequence1',
'mytable6_sequence1',
'mytable7_sequence1',
'mytable7_sequence2',
],
},
};
1;
</programlisting>
</para>
<para>
Comme vous le voyez, cette base de données est très petite avec seulement huit
tables et six séquences. Maintenant, copiez votre fichier
<filename>slon_tools.conf</filename> dans
<filename>/data/pgsql-8.2.3/etc/</filename> et
<filename>/data/pgsql-8.3.3/etc/</filename>.
</para>
</sect3>
<sect3>
<title>Préparer la nouvelle instance &postgres;</title>
<para>
Vous avez maintenant une toute nouvelle seconde instance de &postgres;
fonctionnant sur le port 5433 de la même machine. C'est le moment de préparer
la réception des données à répliquer par &slony1;.
</para>
<orderedlist>
<listitem>
<para>
Slony ne réplique pas les rôles, donc il faut tout d'abord créer tous
les utilisateurs sur la nouvelle instance pour qu'elle soit identique
en terme de rôles/groupes.
</para>
</listitem>
<listitem>
<para>
Créez votre base de données dans le même encodage que la base de données
origine, dans mon cas il s'agit de l'UTF8
<command>/data/pgsql-8.3.3/bin/createdb -E UNICODE -p5433 mydb</command>
</para>
</listitem>
<listitem>
<para>
&slony1; réplique les données, pas les schémas. Donc faites une sauvegarde
de votre schéma avec la commande
<command>/data/pgsql-8.2.3/bin/pg_dump -s mydb > /tmp/mydb.schema</command>
puis importez-le dans la nouvelle instance avec
<command>cat /tmp/mydb.schema | /data/pgsql-8.3.3/bin/psql -p5433 mydb</command>
</para>
</listitem>
</orderedlist>
<para>
La nouvelle base de données est enfin prête à recevoir les données de la
réplication.
</para>
</sect3>
<sect3>
<title>Lancer la réplication &slony1;</title>
<para>
C'est le moment où nous commençons à modifier la base de données de production
en y ajoutant un nouveau schéma contenant toutes les informations de
réplication de &slony1;.
</para>
<para>
La première chose à faire est d'initialiser le schéma de &slony1;. Faites-le
en tant qu'utilisateur postgres, comme dans l'exemple qui suit.
</para>
<note>
<para>
Toutes les commandes commençant avec <command>slonik</command> ne font rien
elles-même. Elles génèrent des commandes qui peuvent être interprétées par
l'outil slonik. Donc exécuter des scripts commençant par slonik_ ne fera
rien à votre base de données. De plus, par défaut, les scripts slonik_
recherchent votre fichier slon_tools.conf dans le sous-répertoire etc du
répertoire PostgreSQL, dans mon cas <filename>/data/pgsql-8.x.x/etc</filename>.
</para>
</note>
<para>
<command>/data/pgsql-8.2.3/slony/slonik_init_cluster > /tmp/init.txt</command>
</para>
<para>
Ouvrez /tmp/init.txt et vérifiez qu'il contient un texte ressemblant à celui
disponible ci-dessous&nbsp;:
</para>
<programlisting>
# INIT CLUSTER
cluster name = replication;
node 1 admin conninfo='host=rome dbname=mydb user=postgres port=5432';
node 2 admin conninfo='host=rome dbname=mydb user=postgres port=5433';
init cluster (id = 1, comment = 'Node 1 - mydb@rome');
# STORE NODE
store node (id = 2, event node = 1, comment = 'Node 2 - mydb@rome');
echo 'Set up replication nodes';
# STORE PATH
echo 'Next: configure paths for each node/origin';
store path (server = 1, client = 2, conninfo = 'host=rome dbname=mydb user=postgres port=5432');
store path (server = 2, client = 1, conninfo = 'host=rome dbname=mydb user=postgres port=5433');
echo 'Replication nodes prepared';
echo 'Please start a slon replication daemon for each node';
</programlisting>
<para>
La première section indique les informations du n&oelig;ud et l'initialisation
du cluster. Puis il y a l'ajout du deuxième n&oelig;ud au cluster. Enfin,
les chemins de communication sont stockés pour les deux n&oelig;uds dans
le schéma de slony.
</para>
<para>
C'est le bon moment pour exécuter la commande&nbsp;:
<command>cat /tmp/init.txt | /data/pgsql-8.2.3/bin/slonik</command>
</para>
<para>
L'exécution sera rapide et indiquera par un affichage le succès.
</para>
<para>
En cas d'échec, les raisons les plus probables sont un problème de droits
sur la base de données, une mauvaise configuration de
<filename>pg_hba.conf</filename> ou une erreur de saisie dans
<filename>slon_tools.conf</filename>. Cherchez le problème et résolvez-le.
Si les schémas slony ont été créés mais que le script échoue toujours,
vous pouvez exécuter le script <command>slonik_uninstall_nodes</command>
pour tout nettoyer. Dans le pire des cas, vous pouvez vous connecter à
chaque base de données et exécuter <command>drop schema _replication
cascade;</command> pour bien nettoyer.
</para>
</sect3>
<sect3>
<title>Le démon slon</title>
<para>
Comme l'indique le résultat de la dernière commande, nous devons maintenant
lancer le démon de réplication slon pour chaque n&oelig;ud. Le démon slon
est le moteur de la réplication. Tous les transferts et tout le reste du
travail sont réalisés par le démon slon. Il est nécessaire d'en avoir un
pour chaque n&oelig;ud. Donc, dans notre cas, nous en avons besoin d'un
pour l'installation 8.2.3 et un autre pour la 8.3.3.
</para>
<para>
Pour lancer celui de la 8.2.3, faites ceci&nbsp;:
<command>/data/pgsql-8.2.3/slony/slon_start 1 --nowatchdog</command>
Ceci va démarrer le démon du n&oelig;ud 1. L'option --nowatchdog est
intéressante car nous faisons une toute petite réplication et que nous
n'avons donc pas besoin de chiens de garde ayant un &oelig;il sur
l'exécution du processus slon.
</para>
<para>
S'il démarre bien, jetez un &oelig;il dans les traces du répertoire
/var/log/slony/slony1/node1/. Elles doivent indiquer que le processus
s'est bien lancé.
</para>
<para>
Nous avons besoin d'en lancer un aussi pour la 8.3.3.
<command>/data/pgsql-8.3.3/slony/slon_start 2 --nowatchdog</command>
</para>
<para>
S'il démarre bien, jetez un &oelig;il dans les traces du répertoire
/var/log/slony/slony1/node2/. Elles doivent indiquer que le processus
s'est bien lancé.
</para>
</sect3>
<sect3>
<title>Ajouter l'ensemble de réplication</title>
<para>
Maintenant, nous avons besoin d'indiquer à slon les tables et séquences à
répliquer. Nous devons donc créer l'ensemble de réplication.
</para>
<para>
Exécutez la commande suivante&nbsp;:
<command>/data/pgsql-8.2.3/slony/slonik_create_set set1 > /tmp/createset.txt</command>
</para>
<para>
<filename>/tmp/createset.txt</filename> peut devenir vraiment gros, cela
dépend du nombre de tables&nbsp;; de toute façon, jetez-y un &oelig;il pour
vérifier qu'il a bien défini toutes les tables et séquences à répliquer.
</para>
<para>
Si vous êtes satisfait du résultat, envoyez le fichier à slonik pour qu'il
soit exécuté&nbsp;:
<command>cat /tmp/createset.txt | /data/pgsql-8.2.3/bin/slonik</command>
Vous verrez des traces indiquant chaque table à répliquer.
</para>
<para>
Et voilà, vous avez défini l'ensemble de tables et séquences à répliquer.
</para>
</sect3>
<sect3>
<title>L'abonnement</title>
<para>
L'étape finale est d'obtenir toutes les données sur la nouvelle base de
données. Cela se fait simplement en utilisant le script d'abonnement.
<command>data/pgsql-8.2.3/slony/slonik_subscribe_set 1 2 > /tmp/subscribe.txt</command>
Le premier argument est l'identifiant de l'ensemble, le second est celui du
n&oelig;ud à abonner.
</para>
<para>
Ce script généré ressemble à ceci&nbsp;:
<programlisting>
cluster name = replication;
node 1 admin conninfo='host=rome dbname=mydb user=postgres port=5432';
node 2 admin conninfo='host=rome dbname=mydb user=postgres port=5433';
try {
subscribe set (id = 1, provider = 1, receiver = 2, forward = yes);
}
on error {
exit 1;
}
echo 'Subscribed nodes to set 1';
</programlisting>
Envoyez-le à slonik&nbsp;:
<command>cat /tmp/subscribe.txt | /data/pgsql-8.2.3/bin/slonik</command>
</para>
<para>
La réplication va maintenant commencer. Elle va copier toutes les données
des tables/séquences appartenant à l'ensemble de réplication. Cela peut
prendre du temps, suivant la taille de la base de données et la puissance
de la machine.
</para>
<para>
Une façon de visualiser la progression est de regarder le contenu des traces
avec la commande&nbsp;:
<command>tail -f /var/log/slony/slony1/node2/log | grep -i copy</command>
Les traces de slony sont verbeuses, mais cela vous permettra de suivre
l'avancée de la réplication initiale. À un moment, vous verrez le message
«&nbsp;copy completed sucessfully in xxx seconds&nbsp;». Cela vous dira que
la réplication initiale est terminée&nbsp;!
</para>
<para>
Une fois que ceci est fait, il va commencer à rattraper l'activité survenue
depuis le début de la réplication initiale. Vous pouvez facilement voir la
progression de ce processus dans la base de données. Connectez-vous à la
base de données maître. Il existe une vue appelée sl_status dans le schéma
de la réplication. Le champ le plus intéressant est st_lag_num_event. Cela
déclare le nombre d'événements slony en retard. 0 est le but à atteindre.
Évidemment, cela dépend de l'activité de votre base de données. Le champ
suivant est st_lag_time, une estimation du temps restant. À considérer
avec prudence, st_lag_num_event étant une mesure bien plus précise.
</para>
<para>
Vous avez maintenant une base de données entièrement répliquée.
</para>
</sect3>
<sect3>
<title>La bascule</title>
<para>
Notre base de données est entièrement répliquée. Il existe différentes options
pour faire la bascule.
</para>
<orderedlist>
<listitem>
<para>
Tout d'abord, modifiez le fichier postgresql.conf pour que la version
8.3.3 utilise le port 5432, de façon à ce qu'il soit prêt dès le
redémarrage.
</para>
</listitem>
<listitem>
<para>
À partir de ce moment, vous êtes hors production. Arrêtez le serveur
8.2.3.
</para>
</listitem>
<listitem>
<para>
Redémarrez le serveur 8.3.3. Cela ne devrait pas poser de problèmes.
</para>
</listitem>
<listitem>
<para>
Supprimez les objets slony du serveur 8.3.3, puis exécutez la commande&nbsp;:
<command>drop schema _replication cascade;</command>
</para>
</listitem>
</orderedlist>
<para>
Vous êtes maintenant en 8.3.3. La mise à jour est terminée avec, on l'espère,
un temps minimal passé hors production. Cette procédure est la façon le plus
simple de le faire.
</para>
</sect3>
</sect2>
</sect1>