La agrupación (clustering) de bases de datos se realiza por varias razones. Los clúster pueden mejorar la disponibilidad, la tolerancia a fallos, e incrementar el rendimiento aplicando un enfoque de "divide y vencerás", ya que el trabajo se distribuye en varias máquinas. La agrupación (clustering) a veces se combina con particionamiento y fragmentación para dividir aún más una tarea compleja grande en unidades más pequeñas y manejables.
El complemento mysqlnd_ms pretende dar soporte a una gran variedad de clústeres de bases de datos de MySQL. Algunos sabores de clúster de bases de datos de MySQL poseen métodos internos para el particionamiento y la fragmentacion, los cuales podrían ser transparentes de usar. El complemetno admite los dos enfoques más comunes: filtración de tabla de Replicación de MySQL, y la fragmentación (particionamiento basada en aplicación).
La Replicación de MySQL admite el particionamiento como filtros que permiten crear esclavos que replican todas las bases de datos o específicas del maestro, o tablas. Es entonces responsabilidad de la aplicación elegir un esclavo según las reglas de los filtros. Se puede usar el filtro node_groups de mysqlnd_ms para dar soporte manual a esto, o usar el filtro de tablas experimental.
El particionamiento manual o fragmentación está soportado a través del filtro de agrupación de nodos, y de las sugerencias SQL a partir de 1.5.0. El filtro node_groups permite asignar un nombre simbólico a un grupo de servidores maestros y esclavos. En el ejemplo, el maestro master_0 y slave_0 forman un grupo con el nombre de Partition_A. Es su responsabilidad decidir lo que haga un grupo. Por ejemplo, se podrían usar grupos de nodos para la fragmentación, y usar los nombres de grupos para direccionar fragmentos como Shard_A_Range_0_100.
Ejemplo #1 Clúster de grupos de nodos
{ "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": [] } } }
Ejemplo #2 Particionamiento manual usando sugerencias SQL
<?php
function select($mysqli, $msj, $sugerencia = '')
{
/* Nota: prueba débil, dos conexiones a dos servidores podrían tener el mismo id de hilo */
$sql = sprintf("SELECT CONNECTION_ID() AS _thread, '%s' AS _hint FROM DUAL", $msj);
if ($sugerencia) {
$sql = $sugerencia . $sql;
}
if (!($res = $mysqli->query($sql))) {
printf("[%d] %s", $mysqli->errno, $mysqli->error);
return false;
}
$fila = $res->fetch_assoc();
printf("%d - %s - %s\n", $fila['_thread'], $fila['_hint'], $sql);
return true;
}
$mysqli = new mysqli("myapp", "usuario", "contraseña", "base_datos");
if (!$mysqli) {
/* Por supuesto, su manejo de errores es mejor... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
}
/* Permitir siempre esclavos */
select($mysqli, "slave_0");
select($mysqli, "slave_1");
/* solamente permtir los servidores del grupo de nodos "Partition_A" */
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
Por omisión, el complemento usará todos los servidores maestros y esclavos configurados para la ejecución de consultas. Pero si una consulta comienza con una sugerencia SQL como /*node_group*/, el complemento considerará únicamente los servidores enumerados en node_group para la ejecución de consultas. Así, las consultas SELECT prefijadas con /*Partition_A*/ úncamente serán ejecutadas en slave_0.