Christophe Nowicki

May 30, 2008

Système de synchronisation conditionnel pour PostgreSQL

Il existe des outils tel que SQLSync permettant de synchroniser les données d’une base PostgreSQL. Mais cette outil, ne permet pas de faire une copie partiel des données.
Dans la plus part des cas, il faut programmer la synchronisation soit même, l’objectif de mon article est de vous proposer une solution simple et élégante.

La problèmatique

Des données sensibles se trouvent dans la base principale et il ne faut synchoniser qu’une partie de ces données vers les autres bases.

L’architecture dispose des caractèristiques suivantes :

  • Le schèma est identique sur chaque base ;
  • Les opèrations d’écriture se font seulement sur la base principale ;
  • Les bases sont accessibles en réseau.

La solution

Pour résoudre le problème, j’ai testé plusieurs approches avant de retenir l’utilisation d’un fonction de hachage dont voici le principe :

  • chaque table doit disposer d’un identifiant unique. (champ id de type SERIAL) ;
  • un programme récupère le couple id et la sum de hachage pour chaque table de chaque base qui doit être synchroniseés ;
  • il compare le couple et si celui-ci est diffèrent alors les données sont mise à jour.

Implementation au niveau de la base de données

Le calcul de la somme de hachage se fait un niveau de la base de données à l’aide d’un fonction :

SELECT id,md5 FROM get_table_md5('nom_de_la_table');
 id |               md5
----+----------------------------------
  4 | 9f3bcd2fae528244669613ae0466cc3c
  5 | 1f3bcd2fa24528244669613ae66cc3czd
...
(42 row)

Voici le code de la function PL/Perl:

CREATE LANGUAGE plperl;
CREATE TYPE table_md5 AS (id INTEGER, md5 TEXT);
CREATE OR REPLACE FUNCTION get_table_md5(varchar) RETURNS SETOF table_md5 AS $$
    my ($rv, $status, $nrows, $row);
    # Get Table OID
    $rv = spi_exec_query("SELECT c.oid AS oid FROM pg_catalog.pg_class c
        LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
        WHERE c.relname LIKE '$_[0]';");
    $status = $rv->{status};
    $nrows = $rv->{processed};
    return undef if ($nrows != 1);
    my $oid = $rv->{rows}[0]->{oid};
    # Get Table attributs
    $rv = spi_exec_query("SELECT attname,atttypid FROM pg_catalog.pg_attribute a
        WHERE a.attrelid = $oid AND a.attnum > 0 AND NOT a.attisdropped");
    $status = $rv->{status};
    $nrows = $rv->{processed};
    return undef if ($nrows < 1);
    my $atts;
    my $atts_not_null;
    foreach my $rn (0 .. $nrows - 1) {
        if ($rv->{rows}[$rn]->{atttypid} == 16) {
            $atts .= " (CASE WHEN $rv->{rows}[$rn]->{attname} THEN 't' ELSE 'f' END) AS $rv->{rows}[$rn]->{attname}";
        } else { 
            $atts .= " $rv->{rows}[$rn]->{attname}::text";
        }
        $atts_not_null .= " (CASE WHEN $rv->{rows}[$rn]->{attname} IS NULL THEN '' ELSE $rv->{rows}[$rn]->{attname} END)";
        $atts .= ',' if ($rn != $nrows - 1);
        $atts_not_null .= ' || ' if ($rn != $nrows - 1);
    }
    # Calc MD5
    my $sql = "SELECT id, MD5($atts_not_null) AS md5 FROM (SELECT $atts FROM $_[0]) AS $_[0];";
    $rv = spi_exec_query($sql);
    $nrows = $rv->{processed};
    foreach my $rn (0 .. $nrows - 1) {
        return_next({
            id  => $rv->{rows}[$rn]->{id},
            md5 => $rv->{rows}[$rn]->{md5}
        });
    }
    return undef;
$$ LANGUAGE plperl;

Pour utiliser cette fonction vous avez besoin du support du language de programmation PL/Perl dans Postgres, celui-ci se trouve dans le paquet Debian : postgresql-plperl-

La gestion des conditions

Le choix des données à synchroniser se fait individuellement pour chaque table à l’aide de la clause WHERE de la manère suivante :

SELECT id,md5 FROM get_table_md5('nom_de_la_table') WHERE id IN(SELECT id FROM nom_de_la_table WHERE nom_de_la_table.champ LIKE 'sync');
 id |               md5
----+----------------------------------
  1 | fdd56eabd4bb997e453e33f0022d46c1
(1 row)

Implementation du script de synchronisation

La synchronisation des données peut être réalisée à l’aide de n’importe quel language de programmation,
il suffit juste de disposer d’un accèss à la base de données.

Voici un exemple de script écrit par Emmanuel Saracco en PHP5 qui se repose sur les modules PEAR suivants :

  • DB : pour l’accès à la base de donnée.
  • Console_Getopt : pour la gestion de la ligne de commande.

Ce script nécessite un fichier de configuration, en voici un exemple.
Ce fichier contiens la configuration des diffèrentes base de données et les conditions sous-forme de clauses where.

Conclusion

Cette méthode de synchronisation fonctionne, elle est en production chez un client pour une base de données de plus de 100 tables, elle permet de synchronisé le contenu d’une base vers deux autres.
Les avantages de cette méthode sont les suivants :

  • le fait de pouvoir choisir le contenu de la clause where permet de réalisé des régles de synchronisation très complexes ;
  • les performances sont très bonnes car les transfert réseau sont limités ;
  • il est possible d’écrire le script de synchronisation avec n’importe quel language de programmation.
Filed under: Work — Tags:, , — cscm @ 14:30

May 26, 2008

Les Français sont-ils des vaches à lait? suite

Allez une copie d’écran pour le plaisir :

Un produit avec une diffèrence de prix de 36% entre la France et la Belgique !!!
Merci Pixmania!

Filed under: Coup de gueule,Hardware — Tags: — cscm @ 13:42

May 1, 2008

Les Français sont-ils des vaches à lait?

Le 5 août 2005, hardware.fr a publié un article intéressant sur la diffèrence de prix entre la France, les USA et l’Allemagne..

A cette époque le taux de change entre l’euro et le dollard était proche de la parité.

Aujourd’hui, un euro vaut pratiquement 1,6 dollar, c’est à dire qu’ à prix égal un produit est 40% moins cher aux USA.

Naivement, je me suis dit que ce taux de change très favorable à l’euro devrait profiter au consommateur français et tirer les prix des produits importés vers le bas.

Mais naturellement, il n’en est rien, la première stratégie des fabriquants est de nous proposer des prix identiques à ceux partiqués outre-atlantique , en voici quelques exemples :

  • Monsieur Sony avec sa Playstation 3 (40Go), nous propose un prix public en France de 399 € et 399$ aux USA.
  • Monsieur Microsoft avec Windows Vista Home Premium à 239 € et 239$ aux USA.
  • Monsieur Apple avec son iPhone (8Go), nous propose un prix public de 399 € et 399$ aux USA.

Cela veut donc dire que ces fabriquants prennent une marge substantielle sur la vente de ces produits en Europe.

Mais il y’a mieux certains fabriquants augmentent leur prix en euro pour faire encore plus de marge.
Le meilleur exemple est un produit hifi haut de game du constructeur Denon, l’amplificateur Home-Cinema AVR-3808.
En effet, son prix public en France est de 2000 € et il est possible de le trouver pour 1300€ en Allemagne et 1200 $ aux USA,
je vous laisse faire le calcul mais le prix est pratiquement multiplié par 3 entre la France et les USA.

Et il est très difficile de justifier une diffèrence de prix de 700 € …

Mais qu’est-ce qui pourrait justifier qu’un produit vendu en France soit trois fois plus cher ?

Voici un début d’explication d’un revendeur Denon agréé :

il y a plusieurs raisons à cela : primo, le dollar est tellement bas, que
les prix américains sont très bas…sauf que vous ne pourrez pas utiliser
l’ampli en France à cause du voltage qui n’est pas du tout le même (110 V).
Pour l’Allemagne, les marges et les charges ne sont du tout les mêmes, et
comme leur marché se portent très biens, ils peuvent casser fortement les
prix, en jouant sur des volumes importants. C’est impossible, à l’heure
actuelle, de lutter contre eux, car nos systèmes de charges et de marges ne
nous le permettent pas.
Est ce une raison valable ?
Par contre, faite attention par rapport à la Garantie car même si vous
bénéficiez d’une garantie internationale, il n’est pas sûr du tout que Denon
France vous répare votre appareil. Ou s’ils le font, vous ne passerez pas en
priorité…

Voici une réponse point par point à ces arguments :

  • vous ne pourrez pas utiliser l’ampli en France à cause du voltage : effectivement le voltage est diffèrent, mais il existent des transformateurs.
  • les marges ne sont pas les mêmes : est-ce que cela veut dire que c’est le constructeur qui impose les marges au revendeur? est-ce bien légal?
  • les charges ne sont pas les mêmes : effectivement le taux de tva est inférieur de 0.6 % en Allemagne, mais il fauderait pousser cette argument très fort pour justifier une diffèrence de prix de 35%…
  • les allemands cassent fortement les prix, en jouant sur des volumes importants : c’est la base du commerce, plus on fait de volume et plus on fait de marge …
  • la garantie : une garantie internationnale qui traine des pieds, c’est très bon pour l’image de marque du constructeur ;0)

Voila, je vous laisse vous faire votre idée, mais moi j’ai vite fait mon choix et j’ai acheté l’ampli aux USA.

Voici la procedure que j’ai suivi :

  • chercher le meilleur prix sur le site PriceGrabber ;
  • ouverture d un compte pour un an sur le site MyUS pour 80$ (51 € ) , si vous ouvrez un compte pour un mois c’est 25$ et ensuite 5$ par mois;
  • ( car certains sites refusent une livraison en France, c est donc un moyen de contourner le probleme)

  • acheter le produit pour 1,119 $ (720 €) chez dbuys ;
  • livraison gratuite aux USA dans une boite aux lettres à mon nom ;
  • rééxpédition en France par DHL pour 200 $ (128€) ;
  • paiement des droits de douane et une tva de 92$ (60€) ;
  • achat d un transformateur 220V->110V chez JR-International pour 119€ ;
  • livraison du transformateur chez moi pour 18€ ;
  • brancher le tout et profiter (mais pas trop, pour garder de bonnes relations avec les voisins ;0)

Le total de mon opèration s’éléve à 51+720+128+60+119+18 = 1096€, soit une diffèrence de 904€ par rapport à la France.

Convaincu(e)?

Filed under: Coup de gueule,Hardware — Tags: — cscm @ 12:38

Powered by WordPress