MySQL : utilisation tables Federated(x)

Les tables "FEDERATED"  sont des tables "distantes" sur un systĂšme diffĂ©rent. 
Les tables de type "FEDERATED" permettent la communication (facile) entre deux bases MySQL (et mĂȘme non-MySQL, par exemple MariaDB). 
Ce plugin est relativement insensible aux versions des bases utilisĂ©es. 
Remarque : pour MariaDB l'utilisation du plugin "ha_federated.so" est Ă  dĂ©conseiller car ce plugin n'est plus maintenu ... mais remplacĂ© par "ha_federatedx.so" qui, lui, est toujours maintenu et a un fonctionnement compatible. MĂȘme avec le plugin "federatedx" il faut ajouter "federated" dans votre fichier de configuration. 
Pour MariaDB le "nec plus ultra" est d'utiliser un nouveau plugin "connect" dont je vous proposerais un test prochainement.

Un petit exemple d'utilisation de "federated" :

  • Je dispose d'une machine "A" qui gĂšre les tables utilisĂ©es par NtopNG, je ne veux pas laisser dans cette machine un trop gros volume de donnnĂ©es car NtopNG est assez consommateur d'espace et j'ai limitĂ© a 30 jours la rĂ©tention des donnĂ©es.
  • Je voudrais disposer d'un historique plus "long" sur une machine "B" pour pouvoir m'amuser Ă  faire des analyses Ă  plus long terme.

La gestion du transfert des données de A vers B m'a posé quelques problÚmes, car les solutions "classiques" ne sont pas faciles à gérer :

  1. Extraction dans une table "tampon" des données de la derniÚre semaine,
  2. Export de la table tampon par mysqldump,
  3. Transfert du ficher export
  4. Import dans une table tampon
  5. Intégration dans la table définitive.

Les rangs de la table principale sont identifiĂ©s par un ID en auto-incrĂ©ment et il est donc aisĂ© de repĂ©rer ceux qui manquent dans la machine "B" et c'est lĂ  que se profile l'utilisation d'une table "FEDERATED" Mysql. 
En effet il suffit de dĂ©clarer dans la machine "B" une table identique Ă  la table principale de "A" avec "engine=FEDERATED" pour accĂ©der de "B" vers "A". La crĂ©ation est simple et toutes les opĂ©rations se font sur la machine "B". Il faut quand mĂȘme vĂ©rifier que "monuser" a bien accĂšs Ă  la base "A" depuis l'adresse de "B" :

  • CrĂ©er un "serveur" :

    create server xxxxxxx 
        foreign data wrapper mysql 
        options (USER 'monuser', PASSWORD 'monpassword', HOST '192.168.x.y', DATABASE 'mabaseA');
  • CrĂ©er une "table" FEDERATED (IDX = PRIMARY KEY) :

    create table table_distante 
    (    ...... 
    KEY    (IDX), 
    .... 
    ) engine=FEDERATED connection='xxxxxxx/table_sur_serveur_A';

Ensuite récupérer les données sur B est hyper simple :

select max(idx) into @IDMAX from table_sur_B;

insert into table_sur_B select * from table_distante 
where idx > @IDMAX;

commit;

Et en plus c'est assez rapide comme le montre la trace suivante :

-------------- 
select max(idx) into @IDMAX from table_sur_B, 
--------------

Query OK, 1 row affected (0,03 sec)

-------------- 
select @IDMAX 
--------------

+----------+ 
| @IDMAX   | 
+----------+ 
| 12775832 | 
+----------+ 
1 row in set (0,00 sec)

-------------- 
insert into table_sur_B select * from table_distante 
where idx > @IDMAX 
--------------

Query OK, 532917 rows affected (7,30 sec) 
Records: 532917  Duplicates: 0  Warnings: 0

Plus de 530 000 rangs en 7,3 secondes ... c'est bien plus rapide que la manip "old style" et surtout bien plus simple ! 
La base distante est ici une base Mysql mais cela marche aussi avec d'autres bases ... Oracle, Postgres ... selon les modules disponibles.

Attention toutefois, un bĂȘte "select" ne passant pas par un index entraĂźnera le transport de toute la table en local (temporaire) et peut durer assez longtemps et ĂȘtre trĂšs consommateur de ressources (disque et mĂ©moire), donc Ă©viter comme la peste les ordres n'utilisant pas correctement un index, mon exemple utilise la Primary Key et est donc trĂšs rapide.