## Partitionnement et fragmentation

Les clusters de base de données sont mis en place pour plusieurs raisons. Les clusters peuvent améliorer la disponibilité, la tolérance aux pannes mais aussi améliorer les performances en suivant une approche du type "diviser pour mieux reigner", sachant que le travail est distribué sur plusieurs machines. Le clustering est quelques fois combiné avec le partitionnement et la fragmentation pour ensuite diviser une énorme tâche complexe en des tâches plus petites et donc plus gérables.

Le plugin mysqlnd_ms a été conçu pour supporter une grande variété de clusters de base de données MySQL. Certaines sortes de clusters de bases de données ont des méthodes internes pour le partitionnement et la fragmentation, les rendant ainsi transparentes à l'utilisation : le filtrage sur les tables de réplication MySQL, et la fragmentation (application basée sur le partitionnement).

La réplication MySQL supporte le partitionnement sous la forme de filtres qui vous permettent de créer des esclaves qui répliquent toutes les bases de données ou une seule base de données (ou des tables) du maîtres. Il est ensuite de la responsabilité de l'application de choisir un esclabe suivant les règles du filtre. Vous pouvez utiliser soit le filtre mysqlnd_ms node_groups pour supporter manuellement ce comportement, ou utiliser le filtre de table expérimental.

Le partitionnement ou la fragmentation manuelle est supporté via le filtre de groupage des noeuds, ainsi qu'avec les astuces SQL depuis la version 1.5.0. Le filtre node_groups vous permet d'assigner un nom symbolique à un groupe de serveurs maîtres ou esclabes. Dans l'exemple, le maître master_0 et slave_0 forment un groupe dont le nom est Partition_A. Il est ensuite entièrement de votre responsabilité que de décider le contenu du groupe. Par exemple, vous pouvez utiliser des groupes de noeuds pour la fragmentation, et utiliser les noms des groupes pour adresse une fragmentation comme like Shard_A_Range_0_100.

Exemple #1 Cluster de groupes de noeuds

    {
      "myapp": {
           "master": {
                "master_0": {
                    "host": "localhost",
                    "socket": "\/tmp\/mysql.sock"
                }
            },
            "slave": {
                "slave_0": {
                    "host": "simulate_slave_failure",
                    "port": "0"
                },
                "slave_1": {
                    "host": "127.0.0.1",
                    "port": 3311
                }
            },
            "filters": {
                "node_groups": {
                    "Partition_A" : {
                        "master": ["master_0"],
                        "slave": ["slave_0"]
                    }
                },
               "roundrobin": []
            }
        }
    }

Exemple #2 Partitionnement manuelle en utilisant des astuces SQL

`<?php
function select($mysqli, $msg, $hint = '')
{
/* Note : test faible, deux connexions vers deux serveurs peuvent avoir le même identifiant de thread */
$sql = sprintf("SELECT CONNECTION_ID() AS _thread, '%s' AS _hint FROM DUAL", $msg);
if ($hint) {
$sql = $hint . $sql;
}
if (!($res = $mysqli->query($sql))) {
printf("[%d] %s", $mysqli->errno, $mysqli->error);
return false;
}
$row = $res->fetch_assoc();
printf("%d - %s - %s\n", $row['_thread'], $row['_hint'], $sql);
return true;
}
$mysqli = new mysqli("myapp", "user", "password", "database");
if (!$mysqli) {
/* Bien évidemment, votre gestionnaire d'erreurs est meilleur... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
}
/* Tous les esclaves sont autorisés */
select($mysqli, "slave_0");
select($mysqli, "slave_1");
/* seuls les serveurs du groupe de noeuds "Partition_A" sont autorisés */
select($mysqli, "slave_1", "/*Partition_A*/");
select($mysqli, "slave_1", "/*Partition_A*/");
?>`

    6804 - slave_0 - SELECT CONNECTION_ID() AS _thread, 'slave1' AS _hint FROM DUAL
    2442 - slave_1 - SELECT CONNECTION_ID() AS _thread, 'slave2' AS _hint FROM DUAL
    6804 - slave_0 - /*Partition_A*/SELECT CONNECTION_ID() AS _thread, 'slave1' AS _hint FROM DUAL
    6804 - slave_0 - /*Partition_A*/SELECT CONNECTION_ID() AS _thread, 'slave1' AS _hint FROM DUAL

Par défaut, le plugin utilisera tous les serveurs maîtres et esclaves configurés pour l'exécution de la requête. Mais si une requête commence avec une astuce SQL comme /*node_group*/, le plugin ne va considérer que les serveurs listés dans le node_group lors de l'exécution de la requête. Aussi, les requêtes de type SELECT préfixées avec /*Partition_A*/ seront exécutées uniquement sur slave_0.