Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

667 lines (566 sloc) 23.718 kb
<?xml version="1.0" encoding="UTF-8"?>
<!-- Dernière modification
le $Date$
par $Author$
révision $Revision$ -->
<sect1 id="maintenance">
<title>Maintenance</title>
<indexterm><primary>maintenir &slony1;</primary></indexterm>
<para>
&slony1; effectue une grande partie de sa maintenance lui-même, dans un
processus de <quote>nettoyage</quote> qui&nbsp;:
<itemizedlist>
<listitem>
<para>
supprime les anciennes données sur les différentes tables du schéma
de <productname>Slony-I</productname>, notamment &sllog1;, &sllog2;
et &slseqlog;&nbsp;;
</para>
</listitem>
<listitem>
<para>
effectue un VACUUM sur certaines tables utilisées par &slony1;. À
partir de la version 1.0.5, ceci inclut &pglistener;&nbsp;; dans les
versions antérieures, vous devez lancer souvent des VACUUM sur cette
table, sinon vous verrez votre réplication ralentir car &slony1; lève
beaucoup d'événements, qui mènent à ce que la table contienne de
nombreuses lignes mortes.
</para>
<para>
Avec certaines versions (la 1.1, peut-être la 1.0.5), il est possible
de ne plus s'embarrasser avec les VACUUM sur ces tables si vous
utilisez quelque chose comme <application>pg_autovacuum</application>
pour gérer le nettoyage de ces tables. Malheureusement, il est possible
que <application>pg_autovacuum</application> ne nettoie pas assez
fréquemment, vous pourrez donc préférer utiliser les VACUUM internes.
Nettoyer la table &pglistener; <quote>trop souvent</quote> est moins
risqué que de ne pas la nettoyer assez.
</para>
<para>
Malheureusement, si vous avez de longues transactions, les VACUUM ne
peuvent pas nettoyer les lignes mortes qui sont plus récentes que les
anciennes transactions toujours en cours. Ceci conduira en particulier
à une forte croissance de &pglistener; et ralentira la réplication.
</para>
</listitem>
<listitem>
<para>
Le bogue <link linkend="dupkey">violation par clef dupliquée</link> a
permis d'isoler un certain nombre de cas d'exceptions assez obscures au
niveau de &postgres;. Donc, dans les versions modernes de &slony1; et
&postgres;, il n'y a pas lieu de s'inquiéter.
</para>
</listitem>
<listitem>
<para>
À partir de la version 1.2, la fonctionnalité <quote>log
switching</quote> est arrivée&nbsp;;de temps en temps (par défaut
une fois par semaine bien que vous pouvez modifier cela en appelant
la procédure stockée <function>logswitch_start()</function>), elle tente
d'interchanger les données entre &sllog1; et &sllog2; afin de réaliser
un <command>TRUNCATE</command> sur les <quote>plus vieilles</quote>
données.
</para>
<para>
Cela signifie que, de manière régulière, ces tables sont complètement
nettoyées ce qui évite qu'elles ne grossissent trop lors d'une charge
importante et qu'elles deviennent impossibles à nettoyer.
</para>
<para>
En version 2.0, <command>DELETE</command> n'est plus utilisé pour
nettoyer les données dans &sllog1; et &sllog2;&nbsp;; à la place, la
logique de la bascule des logs est utilisée fréquemment, à chaque fois
que la boucle de nettoyage ne trouve pas une bascule en cours. Cela
permet de nettoyer proprement ces tables via <command>TRUNCATE</command>.
Ceci élimine le besoin d'un VACUUM pour ces tables.
</para>
</listitem>
</itemizedlist>
</para>
<sect2 id="maintenance-autovac">
<title>Interaction avec l'autovacuum de &postgres;</title>
<indexterm><primary>interaction avec autovacuum</primary></indexterm>
<para>
Les versions récentes de&postgres; proposent un processus
<quote>autovacuum</quote> qui détecte les modifications sur les tables et
la création de lignes mortes, puis nettoie ces tables, <quote>à la
demande</quote>. On a constaté que cela peut interagir de manière négative
avec la politique de VACUUM de &slony1; sur ces propres tables.
</para>
<para>
&slony1; demande des VACUUM sur ses tables immédiatement après avoir complété
les transactions qui sont sensées supprimer de vieilles données, ce qui est
considéré comme le meilleur moment pour le faire. Il semble que l'autovacuum
détecte les changements un peu trop tôt, et lance un VACUUM alors que les
transactions ne sont pas terminées, ce qui est relativement inutile. Il
apparaît préférable de configurer l'autovacuum pour éviter les tables de
configuration gérées par &slony1;.
</para>
<para>
La requête suivante identifie les tables que l'autovacuum ne doit pas traiter
(remplacez le nom du cluster par celui de votre configuration locale)&nbsp;:
</para>
<programlisting>
moncluster=# select oid, relname from pg_class where relnamespace = (select oid from pg_namespace where nspname = '_' || 'monCluster') and relhasindex;
oid | relname
-------+--------------
17946 | sl_nodelock
17963 | sl_setsync
17994 | sl_trigger
17980 | sl_table
18003 | sl_sequence
17937 | sl_node
18034 | sl_listen
18017 | sl_path
18048 | sl_subscribe
17951 | sl_set
18062 | sl_event
18069 | sl_confirm
18074 | sl_seqlog
18078 | sl_log_1
18085 | sl_log_2
(15 rows)
</programlisting>
<para>
La requête suivante remplira la table <envar>pg_catalog.pg_autovacuum</envar>
avec les informations de configuration adéquates&nbsp;:
<command>INSERT INTO pg_catalog.pg_autovacuum (vacrelid, enabled)
SELECT oid, 'f' FROM pg_catalog.pg_class
WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = '_' || 'monCluster')
AND relhasindex;</command>
</para>
</sect2>
<sect2><title>Chiens de garde&nbsp;: garder les Slons en vie</title>
<indexterm><primary>Chiens de garde pour garder en vie les démons slon</primary></indexterm>
<para>
Il y a deux scripts <quote>chiens de garde</quote> disponibles pour surveiller
la réplication et relancer les processus <application>slon</application>
lorsqu'ils meurent pour telle ou telle raison, par exemple une
<quote>coupure</quote> réseau qui provoque une perte de connectivité.
</para>
<para>
Ils pourraient vous être utiles...
</para>
<para>
La <quote>meilleure et nouvelle</quote> façon de gérer les processus <xref
linkend="slon"/> se fait via une combinaison de <xref linkend="mkslonconf"/>,
qui crée un fichier de configuration pour chaque n&oelig;ud d'un cluster, et
<xref linkend="launchclusters"/> qui utilise ces fichiers de configuration.
</para>
<para>
Cette approche est préférable aux anciens systèmes de <quote>chiens de
garde</quote> car vous pouvez <quote>pointer</quote> précisément, dans chaque
fichier de configurationn, le paramètrage désiré pour chaque n&oelig;ud, sans
avoir à vous préoccuper des options que le script chien de garde vous propose
(ou pas). Ceci est particulièrement important si vous utilisez le <link
linkend="logshipping">log shipping</link>, auquel cas oublier l'option
<command>-a</command> peut ruiner le n&oelig;ud destinataire du log shipping
et ruiner par là-même votre journée.
</para>
</sect2>
<sect2 id="gensync"><title>En parallèle aux chiens de garde&nbsp;:
generate_syncs.sh</title>
<indexterm><primary>générer des SYNC</primary></indexterm>
<para>
Un nouveau script est apparu dans &slony1; 1.1, il s'agit de
<application>generate_syncs.sh</application>, qui est utilise dans les
situations suivantes.
</para>
<para>
Supposons que vous avez un serveur non fiable sur lequel le démon
<application>slon</application> ne fonctionne pas en continu, en rentrant de
week-end vous vous trouverez peut-être la situation suivante&nbsp;:
</para>
<para>
Le vendredi soir, quelque chose s'est <quote>cassé</quote> et le temps que la
base de donnée redémarre, aucun des démons <application>slon</application>
n'a survécu. Votre application en ligne a ensuite connu trois jours
de charge transactionnelle relativement forte.
</para>
<para>
Lorsque vous redémarrez <application>slon</application> le lundi, il n'y a
pas eu de synchronisation sur le maître depuis vendredi, ce qui fait que le
prochain <quote>ensemble de SYNC</quote> comprendra toutes les modifications
entre vendredi et lundi. Aïe&nbsp;!</para>
<para>
Si vous lancez <application>generate_syncs.sh</application> via une tache cron
toute les 20 minutes, cela créera de force des événements
<command>SYNC</command> sur l'origine, ce qui implique qu'entre vendredi et
lundi, les nombreuses mises à jour seront découpées en plus de 100 ensembles
de SYNC, qui pourront être appliqués de manière incrémentale, rendant la
restauration moins déplaisante.
</para>
<para>
Notez que si les <command>SYNC</command> <emphasis>sont</emphasis> exécutés
régulièrement, ce scripts ne fera rien de particulier.
</para>
</sect2>
<sect2><title>Tester l'état de &slony1;</title>
<indexterm><primary>tester le statut du cluster</primary></indexterm>
<para>
Dans le répertoire <filename>tools</filename>, vous trouverez des scripts
&lteststate; nommés <filename>test_slony_state.pl</filename> et
<filename>test_slony_state-dbi.pl</filename>. Le premier utilise l'interface
Perl/DBI, l'autre utilise l'interface PostgreSQL.
</para>
<para>
Les deux font essentiellement la même chose, c'est-à-dire se connecter à un
n&oelig;ud &slony1; (celui de votre choix) et, à partir de là, détermine la
liste des n&oelig;uds du cluster. Ensuite ils lancent une série de requêtes
(en lecture seule, donc sans danger) afin de parcourir différentes tables à
la recherche de différentes conditions susceptibles de revéler des problèmes,
telles que&nbsp;:
</para>
<itemizedlist>
<listitem>
<para>
Gonflement des tables comme pg_listener, sl_log_1, sl_log_2, sl_seqlog&nbsp;;
</para>
</listitem>
<listitem>
<para>
Voies d'écoute&nbsp;;
</para>
</listitem>
<listitem>
<para>
Analyse de la propagation des événements&nbsp;;
</para>
</listitem>
<listitem>
<para>
Analyse de la propagation des confirmations.
</para>
<para>
Si la communication est <emphasis>légèrement</emphasis> perturbée, la
réplication peut fonctionner, mais les confirmations peuvent ne pas être
retournées, ce qui empêche les n&oelig;uds de nettoyer les vieux
événements et les anciennes données de réplication.
</para>
</listitem>
</itemizedlist>
<para>
Lancer ce script une fois par heure ou une fois par jour peut vous aider à
détecter les symptomes précurseurs de certains problèmes, avant même que
cela conduise à une dégradation des performances.
</para>
</sect2>
<sect2><title>Scripts de test de la réplication</title>
<para>
Dans le répertoire <filename>tools</filename>, on peut trouver quatre scripts
qui peuvent être utilisés pour surveiller des instances &slony1;&nbsp;:
<itemizedlist>
<listitem>
<para>
<command>test_slony_replication</command> est un script Perl auquel
vous pouvez passer les informations de connexion d'un n&oelig;ud
&slony1;. Il teste alors la table <xref linkend="table.sl-path"/> et
d'autres informations sur ce n&oelig;ud afin de déterminer la forme de
l'ensemble de réplication choisi.
</para>
<para>
Ensuite il injecte des requêtes de test dans la table nommée
<envar>slony_test</envar> qui est définie comme ci-dessous, et qui doit
être ajoutée à l'ensemble des tables répliquées&nbsp;:
<programlisting>CREATE TABLE slony_test (
description text,
mod_date timestamp with time zone,
"_Slony-I_testcluster_rowID" bigint DEFAULT nextval('"_testcluster".sl_rowid_seq'::text) NOT NULL
);</programlisting>
</para>
<para>
La dernière colonne de la table est définie par &slony1; comme une clé
primaire manquante...
</para>
<para>
Ce script génère une ligne de sortie pour chaque n&oelig;ud &slony1;
actif pour l'ensemble de réplication défini dans un fichier nommé
<filename>cluster.fact.log</filename>.
</para>
<para>
Il y a une option additionelle, <option>finalquery</option>, qui vous
permet de passer une requête SQL spécifique à votre application pour
déterminer l'état de votre application.
</para>
</listitem>
<listitem>
<para>
<command>log.pm</command> est un module Perl module qui gère les logs
des scripts Perl.
</para>
</listitem>
<listitem>
<para>
<command>run_rep_tests.sh</command> est un script <quote>wrapper</quote>
qui lance <command>test_slony_replication</command>.
</para>
<para>
Si vous avez plusieurs clusters &slony1;, vous pouvez placer dans ce
fichier la configuration pour se connecter à tous ces clusters.
</para>
</listitem>
<listitem>
<para>
<command>nagios_slony_test</command> est un script qui a été construit
pour interroger les fichiers logs afin de pouvoir lancer le test de
réplication régulièrement (nous le laissons toutes les six minutes) et
qu'un outil de supervision tel que <ulink
url="http://www.nagios.org/"> <productname>Nagios</productname></ulink>
puisse utiliser le script pour surveiller l'état indiqué dans ces logs.
</para>
<para>
Il semble plus efficace qu'une tache <application>cron</application>
lance les tests et que <productname>Nagios</productname> vérifie le
résultat plutôt que de voir <productname>Nagios</productname> lancer
directement les tests. Ces tests peuvent vérifier l'ensemble du cluster
&slony1; d'un seul coup, plutot que de voir <productname>Nagios</productname>
provoquer des mises à jour en permanence.
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
<sect2><title>Autres tests de réplication</title>
<indexterm><primary>tester la réplication</primary></indexterm>
<para>
La méthodologie de la section précédente est conçu avec un vue pour minimiser
le coût des requêtes de tests&nbsp;; sur un cluster très chargé, supportant
des centaines d'utilisateurs, le coût associé aux quelques requêtes de test
n'est pas un point important et le temps de configuration des tables et des
injecteurs de données est très élevé.
</para>
<para>
Trois autres méthodes sont apparus pour analyser l'état de la
réplication&nbsp;:
</para>
<itemizedlist>
<listitem>
<para>
Pour un test orienté sur l'application, il est utile de créer une vue
sur une table fréquemment mise à jour pour remonter des informations
spécifiques à l'application.
</para>
<para>
Par exemple, on peut chercher soit des statistiques sur les objets
applicatifs les plus récents, soit les transactions de l'application.
Par exemple&nbsp;:
</para>
<para>
<command>CREATE VIEW replication_test AS
SELECT now() - txn_time AS age, object_name
FROM transaction_table
ORDER BY txn_time DESC
LIMIT 1;</command>
</para>
<para>
<command>CREATE VIEW replication_test AS
SELECT now() - created_on AS age, object_name
FROM object_table
ORDER BY id DESC
LIMIT 1;</command>
</para>
<para>
Il y a un inconvénient&nbsp;: cette approche nécessite que vous ayez une
activité constante sur le système impliquant la création de nouvelles
transactions de manière régulière. Si quelque chose ne fonctionne pas
dans votre application, vous obtiendrez des fausses alertes en provenance
de la réplication alors même que la réplication fonctionne correctement.
</para>
</listitem>
<listitem>
<para>
La vue &slony1; nommée <envar>sl_status</envar> fournit des informations
sur la synchronisation des différents n&oelig;uds. Son contenu n'est
intéressant que sur les n&oelig;uds origine car les événements générés
sur les autres n&oelig;uds peuvent généralement être ignorés.
</para>
</listitem>
<listitem>
<para>
Voir également la discussion sur <xref linkend="slonymrtg"/>.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2><title>Journaux applicatifs</title>
<indexterm><primary>journaux applicatifs</primary></indexterm>
<para>
Les démons <xref linkend="slon"/> génère des journaux applicatifs plus ou
moins verbeux, selon le niveau de débogage activé. Dans ce cas, vous
pouvez&nbsp;:
<itemizedlist>
<listitem>
<para>
Utiliser un programme de rotation des journaux applicatifs comme
<application>rotatelogs</application> d'<productname>Apache</productname>
pour avoir une séquence de journaux applicatifs et éviter d'avoir des
journaux trop gros&nbsp;;
</para>
</listitem>
<listitem>
<para>
Purgez régulièrement les vieux journaux applicatifs.
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
<sect2><title>mkservice</title>
<indexterm><primary>mkservice pour BSD </primary></indexterm>
<sect3><title>slon</title>
<para>
Ce script crée un répertoire pour le service slon qui pourra être utilisé
avec la commande svscan de daemontools. Ce script utilise multilog de manière
très basique, ce qui semble être standard pour les installations daemontools
/ multilog. Si vous souhaitez une gestion intelligente des journaux applicatifs,
consultez la section logrep ci-dessous. Actuellement, ce script a des
possibilités de gestion d'erreurs très limitées.
</para>
<para>
Pour les usages non-interactifs, configurez les variables d'environnement
suivantes&nbsp;: <envar>BASEDIR</envar>, <envar>SYSUSR</envar>,
<envar>PASSFILE</envar>, <envar>DBUSER</envar>, <envar>HOST</envar>,
<envar>PORT</envar>, <envar>DATABASE</envar>, <envar>CLUSTER</envar> et
<envar>SLON_BINARY</envar>. Si une seule de ces valeurs n'est pas définie,
le script demande les informations de manière interactive.
</para>
<itemizedlist>
<listitem>
<para>
<envar>BASEDIR</envar>, l'emplacement où la structure du répertoire du
service slon sera créée. Il ne faut <emphasis>pas</emphasis> que ce soit
le répertoire <filename>/var/service</filename>&nbsp;;
</para>
</listitem>
<listitem>
<para>
<envar>SYSUSR</envar>, l'utilisateur unix qui lancera le processus slon
(et multilog)&nbsp;;
</para>
</listitem>
<listitem>
<para>
<envar>PASSFILE</envar>, l'emplacement du fichier
<filename>.pgpass</filename> (par défaut
<filename>~sysusr/.pgpass</filename>)&nbsp;;
</para>
</listitem>
<listitem>
<para>
<envar>DBUSER</envar>, l'utilisateur postgres que slon doit utiliser (par
défaut slony)&nbsp;;
</para>
</listitem>
<listitem>
<para>
<envar>HOST</envar>, l'adresse du serveur ou slon doit se connecter (par
défaut localhost)&nbsp;;
</para>
</listitem>
<listitem>
<para>
<envar>PORT</envar>, le port de connexion (par défaut 5432)&nbsp;;
</para>
</listitem>
<listitem>
<para>
<envar>DATABASE</envar>, la base de données sur laquelle slon se connecte
(par défaut dbuser)&nbsp;
</para>
</listitem>
<listitem>
<para>
<envar>CLUSTER</envar>, le nom du cluster Slony1 (par défaut database)&nbsp;;
</para>
</listitem>
<listitem>
<para>
<envar>SLON_BINARY</envar>, le chemin complet vers le binaire slon (par
défaut <command>which slon</command>).
</para>
</listitem>
</itemizedlist>
</sect3>
<sect3><title>logrep-mkservice.sh</title>
<para>
Ce script utilise <command>tail -F</command> pour extraire des données des
journaux applicatifs en vous permettant d'utiliser des filtres multilog (via
l'option CRITERIA) afin de créer des journaux de transactions spécifiques.
Le but est de fournir un moyen de surveiller les journaux de transactions en
temps réel en quête de données <quote>intéressante</quote> sans devoir
modifier le journal applicatif initial ou gacher des ressources CPU/IO
en parcourant les journaux régulièrement.
</para>
<para>
Pour une utilisation non interactive, il faut configurer les variables&nbsp;:
<envar>BASEDIR</envar>, <envar>SYSUSR</envar>, <envar>SOURCE</envar>,
<envar>EXTENSION</envar> et <envar>CRITERIA</envar>. Si une seule de ces
options n'est pas définie, le script demande interactivement les informations
de configuration.
</para>
<itemizedlist>
<listitem>
<para>
<envar>BASEDIR</envar>, l'emplacement où sera créée la structure du
répertoire du service de logrep. Il ne faut <emphasis>pas</emphasis> que
ce soit le répertoire <filename>/var/service</filename>.
</para>
</listitem>
<listitem>
<para>
<envar>SYSUSR</envar>, l'utilisateur unix qui lancera le service.
</para>
</listitem>
<listitem>
<para>
<envar>SOURCE</envar>, le nom du service de log que vous voulez utiliser.
</para>
</listitem>
<listitem>
<para>
<envar>EXTENSION</envar>, une balise pour différencier ce logrep de ceux
qui utilisent la même source.
</para>
</listitem>
<listitem>
<para>
<envar>CRITERIA</envar>, le filtre multilog que vous voulez utiliser.
</para>
</listitem>
</itemizedlist>
<para>
Un exemple trivial consiste à produire un journal applicatif de tous les
messages d'erreur slon qui pourraient être utilisés pour déclencher une
alerte nagios&nbsp;:
<command>EXTENSION='ERRORS'</command>
<command>CRITERIA="'-*' '+* * ERROR*'"</command>
(on relance la surveillance en déclenchant une rotation des journaux
applicatifs avec <command>svc -a $svc_dir</command>)
</para>
<para>
Une application plus intéressante est la surveillance de la progression
d'une souscription d'un n&oelig;ud&nbsp;:
<command>EXTENSION='COPY'</command>
<command>CRITERIA="'-*' '+* * ERROR*' '+* * WARN*' '+* * CONFIG enableSubscription*' '+* * DEBUG2 remoteWorkerThread_* prepare to copy table*' '+* * DEBUG2 remoteWorkerThread_* all tables for set * found on subscriber*' '+* * DEBUG2 remoteWorkerThread_* copy*' '+* * DEBUG2 remoteWorkerThread_* Begin COPY of table*' '+* * DEBUG2 remoteWorkerThread_* * bytes copied for table*' '+* * DEBUG2 remoteWorkerThread_* * seconds to*' '+* * DEBUG2 remoteWorkerThread_* set last_value of sequence*' '+* * DEBUG2 remoteWorkerThread_* copy_set*'"</command>
</para>
<para>
Si vous avez une trace d'abonnement, alors il est facile de déterminer si un
n&oelig;ud donné est en train de réaliser une copie ou une autre activité de
souscription. Si les journaux applicatifs ne sont pas vide et ne se terminent
pas par <command>"CONFIG enableSubscription: sub_set:1"</command> (où 1 est
le numéro d'ensemble de réplication que vous avez abonné) alors le slon est
au milieu d'une copie initiale.
</para>
<para>
Si vous surveillez l'horodatage de modification du journal applicatif de
votre n&oelig;ud primaire pour déterminer si le slon est tombé dans le coma,
vérifier cette trace d'abonnement est un bon moyen d'éviter de stopper le
n&oelig;ud alors qu'un abonnement est en cours. En bonus, puisque les slons
utilisent svscan, vous pouvez simplement détruire le fichier (via l'interface
svc) et laisser svscan le recommencer plus tard. J'ai également découvert que
les traces de COPY sont pratiques pour suivre de manière interactive
l'activité des abonnements.
</para>
</sect3>
</sect2>
</sect1>
Jump to Line
Something went wrong with that request. Please try again.