mardi 14 octobre 2008

Chargement de données avec Slony

Introduction

Slony est un outil de réplication basé sur des triggers. Dans le cas de l'import ou de la mise à jour massive des données de la base, le retard de réplication peut devenir un réel problème. En effet, un UPDATE sur 100 mille lignes va générer 100 mille instructions à exécuter sur les esclaves. Il peut donc devenir judicieux de ne pas utiliser la réplication Slony dans le cas cité.

Première méthode

Cette méthode consiste à supprimer totalement la configuration slony des bases de données en supprimant purement et simplement les schemas créés par slony, c'est à dire les schemas de la forme _nomdecluster (au sens slony bien sûr, http://slony.info/documentation/clustername.html), et à arrêter les démons slon de chaque machine faisant partie du cluster.
Ensuite les données sont importées sur le provider source, et le cluster est réinitialisé en réutilisant les scripts qui avaient servi à initialiser la configuration. L'initialisation du cluster va engendrer la recopie par slony des données du provider sur l'ensemble des receivers en utilisant la commande postgresql COPY qui est très performante.

Seconde méthode

Cette méthode consiste à désactiver la réplication sur l'ensemble des tables concernées sur chacune des bases faisant partie du cluster Slony. Ensuite les données sont importées et la réplication est réactivée.
Cette méthode s'appuie sur les fonctions Slony alterTableRestore et alterTableForReplication qui respectivement désactive et active les triggers sur la table dont l'identifiant est fourni en paramètre.


Voici par exemple le déroulement de cette méthode sur ma plateforme (mes tables se nomment 's_xxx') :

Génération des scripts pour désactiver la réplication et vider les tables

schema=_nomdecluster
rm -f /var/tmp/disabletriggers-$schema.sql /var/tmp/truncate-$schema.sql
psql ma_base -U mon_user -c \
"SELECT 'SELECT $schema.altertablerestore('||relname||');' FROM pg_class where relname like E's\\\\_%'" >> /var/tmp/disabletriggers-$schema.sql
psql ma_base -U mon_user -c \
"SELECT 'TRUNCATE TABLE '||relname||';' FROM pg_class where relname like E's\\\\_%'" >> /var/tmp/truncate-$schema.sql

Génération des scripts pour réactiver la réplication

schema=_nomdecluster
rm -f /var/tmp/enabletriggers-$schema.sql
psql ma_base -U mon_user -c "SELECT 'SELECT $schema.alterTableForReplication('||relname||');' FROM pg_class where relname like E's\\\\_%'" >> /var/tmp/enabletriggers-$schema.sql

Désactivation de la réplication

schema=_nomdecluster
psql ma_base -U mon_user < /var/tmp/disabletriggers-$schema.sql

Suppression des données existentes

psql ma_base -U mon_user < /var/tmp/truncate-$schema.sql

Chargement des données à partir d'un dump

# On se rend dans le répertoire où se trouvent les backups
cd /dir
schema=_clustername
dumpfile=$schema-lastbackup.sql.gz

# On génère la liste des objets à restaurer
zcat $dumpfile |pg_restore -l|egrep -v 'slony' > /tmp/objects.list

# On restaure les données de la base ma_base
zcat $dumpfile |pg_restore -d ma_base --no-owner --data-only -L /tmp/objects.list

Rétablissement de la réplication

psql ma_base -U mon_user < /var/tmp/enabletriggers-$schema.sql

Il est clair que les écritures autres que le chargement des données doivent être interrompues au niveau applicatif pour ne pas désynchroniser les bases de données entre elles.

Conclusion

Il y a donc la possibilité de charger des données sans utiliser la réplication Slony courante, ce qui permet d'accélérer le processus. Cependant, cela demande dans ces cas là de désactiver le service (s'il y a besoin de supprimer les données au préalable) ou au moins de désactiver les écritures.
La seconde méthode peut aussi être utilisée dans le cas où vous n'auriez plus sous la main les scripts d'initialisation de la configuration Slon, ce qui ne devrait pas être le cas pour des plateformes de production.

Aucun commentaire: