Posts tagged with “sandbox”
Replicación semi-síncrona con MySQL 5.5
El problema más grave de la replicación en MySQL es su funcionamiento asíncrono. Cuando se añade o modifica algún dato en el master, este commitea los datos en local sin esperar a que los slaves lo hagan. Esto normalmente no supone un gran problema, ya que la replicación, si no hay ningún problema con índices o con la red, es casi instantanea. Pero aún así se pueden dar algunos problemas:
El master commitea los datos sin esperar. Durante un tiempo, aunque pequeño, master y slave tendrán datos diferentes. Contra mas alto sea el valor seconds behind master, mayor será el problema.
El master no comprueba que los esclavos hayan recibido los binlogs con los cambios.
El master no comprueba que los esclavos hayan hecho efectivos los cambios en sus bases de datos.
Este es un problema solucionado en MySQL Cluster, donde la replicación es totalmente síncrona. Los nodos no commitean los cambios hasta que estos se hayan escrito correctamente en los node groups que correspondan. Si esto no es así, se hace un rollback. Pero en la replicación normal no tenemos tanta suerte.
Una de las novedades de MySQL 5.5 viene a medio solventar el problema. Con esta nueva versión de desarrollo disponemos de replicación semi-síncrona. Algo es algo :)
Su funcionamiento es simple. Ahora el master antes de hacer commit espera a que al menos uno de los slaves reciba los logs binarios. Pero aún así hay que tener en cuenta lo siguiente:
El master solamente comprueba que un slave haya recibido los logs, pero no que si lo ha podido escribir correctamente o no. Esto es, no importa el estado del SQL Thread.
Podemos tener 1000 slaves, pero con que solo uno reciba los logs ya se da por bueno.
Si pasado un tiempo ninguno de los esclavos recibe los logs, el master cambia a modo asíncrono commiteando los cambios.
Vamos a hacer unas pruebas. Necesitaremos dos cosas, MySQL 5.5 y sandbox :) Creamos un entorno de replicación con un master y dos slaves:
punisher@shyris:~$ make_replication_sandbox --how_many_slaves=2 /home/punisher/MySQL/mysql-5.5.1-m2-linux-x86_64-glibc23.tar.gz installing and starting master installing slave 1 installing slave 2 starting slave 1 .. sandbox server started starting slave 2 . sandbox server started initializing slave 1 initializing slave 2
Una vez hecho, debemos cargar el plugin que nos permite hacer uso de la replicación semi-síncrona en todos los hosts:
master [localhost] {msandbox} ((none)) > INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; Query OK, 0 rows affected (0.00 sec) slave1 [localhost] {msandbox} ((none)) > INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.00 sec) slave2 [localhost] {msandbox} ((none)) > INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.00 sec)
A continuación, debemos habilitar su uso en los ficheros de configuración:
Master: rpl_semi_sync_master_enabled=1; Slaves: rpl_semi_sync_slave_enabled=1;
Reiniciamos mysql y ya lo tenemos :) Creamos una base de datos llamada prueba y comprobamos si al menos un slave ha recibido el binlog:
master [localhost] {msandbox} ((none)) > create database pruebas; Query OK, 1 row affected (0.00 sec) master [localhost] {msandbox} ((none)) > SHOW STATUS LIKE 'Rpl_semi_sync%tx'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | Rpl_semi_sync_master_no_tx | 0 | | Rpl_semi_sync_master_yes_tx | 1 | +-----------------------------+-------+ 2 rows in set (0.00 sec)
Rpl_semi_sync_master_yes_tx es el número de queries correctamente replicadas. Rpl_semi_sync_master_no_tx es el número de queries que no se han replicado.
Hay que tener en cuenta, que estamos hablando de IO no de SQL. Para comprobarlo, paramos el SQL thread en los dos nodos:
slave1 [localhost] {msandbox} ((none)) > STOP SLAVE SQL_THREAD; Query OK, 0 rows affected (0.00 sec) slave2 [localhost] {msandbox} ((none)) > STOP SLAVE SQL_THREAD; Query OK, 0 rows affected (0.00 sec)
Y a continuación insertamos un dato en el master:
master [localhost] {msandbox} (pruebas) > create table t(i int(10)); Query OK, 0 rows affected (0.00 sec) master [localhost] {msandbox} (pruebas) > SHOW STATUS LIKE 'Rpl_semi_sync%tx'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | Rpl_semi_sync_master_no_tx | 0 | | Rpl_semi_sync_master_yes_tx | 2 | +-----------------------------+-------+ 2 rows in set (0.00 sec)
Los slaves han recibido los datos, eso es suficiente para el master y se da por bueno. Ahora vamos a parar el IO Thread:
slave1 [localhost] {msandbox} ((none)) > STOP SLAVE IO_THREAD; Query OK, 0 rows affected (0.00 sec) slave2 [localhost] {msandbox} ((none)) > STOP SLAVE IO_THREAD; Query OK, 0 rows affected (0.00 sec)
Y volvemos a meter datos en el master:
master [localhost] {msandbox} (pruebas) > create table z(i int(10)); Query OK, 0 rows affected (10.00 sec) master [localhost] {msandbox} (pruebas) > SHOW STATUS LIKE 'Rpl_semi_sync%tx'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | Rpl_semi_sync_master_no_tx | 1 | | Rpl_semi_sync_master_yes_tx | 2 | +-----------------------------+-------+ 2 rows in set (0.00 sec)
La query ha tardado 10 segundos en commitearse. Si durante esos 10 segundos ninguno de los slaves ha recibido los binlogs, el master hace commit y se cuenta como una query no sincronizada.
MySQL SandBox, el mejor entorno de pruebas
Juguetear con MySQL es divertido, pero la preparación de los distintos servidores un coñazo. Distintos sockets, distintos puertos, establecer los usuarios y permisos… Existe una utilidad para convertir MySQL en una zona de juego, SandBox:
Esta herramienta te permite por ejemplo, mediante un simple comando, crear una estructura de replicación circular con 20 servidores MySQL :P
Instalación
Hacen falta dos cosas, SandBox y un tar.gz con los binarios de Mysql (que se descargan de la propia web de MySQL). Una vez que lo tenemos, procedemos a instalar SandBox:
Como Root:
perl Makefile.PL
make
make test
make install
Como Usuario:
export PATH=$HOME/usr/local/bin:$PATH
export PERL5LIB=$HOME/usr/local/lib/perl5/site_perl/5.8.8
perl Makefile.PL PREFIX=$HOME/usr/local
make
make test
make install
Puesta en marcha
Imaginemos que queremos montar un sistema de replicación con un maestro y 10 esclavos :) Lo que antes era un infierno ahora se resume en:
make_replication_sandbox --how_many_slaves=10 /tmp/mysql-5.1.37-linux-i686-glibc23.tar.gz
installing and starting master
installing slave 1
installing slave 2
installing slave 3
installing slave 4
[...]
replication directory installed in $HOME/sandboxes/rsandbox_5_1_37
Listo!
Para ejecutar un comando en todos los servidores:
/home/sandboxes/use_all "show databases"
master
Database
information_schema
mysql
test
server: 1:
Database
information_schema
mysql
test
...
Cada MySQL escucha en un puerto y tiene un socket propio. Los puestos los podeis saber con un simple netstat:
[punisher@miguel sandboxes]$ netstat -putan
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:23552 0.0.0.0:* LISTEN 9986/mysqld
tcp 0 0 0.0.0.0:23553 0.0.0.0:* LISTEN 10609/mysqld
tcp 0 0 0.0.0.0:23554 0.0.0.0:* LISTEN 10706/mysqld
tcp 0 0 0.0.0.0:23555 0.0.0.0:* LISTEN 10803/mysqld
tcp 0 0 0.0.0.0:23556 0.0.0.0:* LISTEN 10900/mysqld
tcp 0 0 0.0.0.0:23557 0.0.0.0:* LISTEN 10998/mysqld
tcp 0 0 0.0.0.0:23558 0.0.0.0:* LISTEN 11096/mysqld
tcp 0 0 0.0.0.0:23559 0.0.0.0:* LISTEN 11194/mysqld
tcp 0 0 0.0.0.0:23560 0.0.0.0:* LISTEN 11292/mysqld
tcp 0 0 0.0.0.0:23561 0.0.0.0:* LISTEN 11389/mysqld
tcp 0 0 0.0.0.0:23562 0.0.0.0:* LISTEN 11487/mysqld
Para saber los sockets:
[punisher@miguel ~]$ ls -la /tmp/mysql_sandbox235*
Para pararlos/arrancar todos:
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23552.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23553.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23554.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23555.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23556.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23557.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23558.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23559.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23560.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23561.sock
srwxrwxrwx 1 punisher users 0 sep 7 16:44 /tmp/mysql_sandbox23562.sock
$HOME/sandboxes/start_all $HOME/sandboxes/stop_all
Para acceder a uno en particular:
Con la herramienta mysql (clave de root msandbox) o mediante unos script:
$HOME/sandboxes/rsandbox_5_1_37/m (master)
$HOME/sandboxes/rsandbox_5_1_37/s1 (slave 1)
$HOME/sandboxes/rsandbox_5_1_37/s2 (slave 2)
etc.



