Como hacer un «snapshot» en MySQL
s una chorrada y bien conocida, aunque a mí me costó averiguar cuál es la solución más rápida y fiable –¿soy sólo yo el lento o también ocurre lo mismo a otros?–, así que aquí va por si a alguien le sirve.
MySQL funciona muy bien para mantener réplicas (slaves) de un servidor maestro (master), pero a veces hay algunos problemas:
- El comando
LOAD DATA FROM MASTER
desde la réplica no está recomendado. - La base de datos es muy grande y toma mucho tiempo hacer el “mysqldump”, es mucho más rápido hacerlo con los mysqlhotcopy que sólo copia los ficheros.
- Antes de hacer el mysqldump (si se hace) hay que obtener el estado del “binlog” del servidor para indicarlo en la réplica.
La mejor opción es hacer copia de los ficheros de la base de datos con el mysqlhotcopy
y además indicarle que grabe en una tabla el estado del “binlog”. Con esto tendremos una copia rápida de la base de datos en “producción” que nos servirá para iniciar fácilmente una nueva réplica y/o reparar una que haya perdido el sincronismo o coherencia con el máster (suele suceder).
Para ello primero hay que crear esa tabla (está documentado en perldoc mysqlhotcopy
).
CREATE TABLE log_pos ( host varchar(60) NOT null, time_stamp timestamp(14) NOT NULL, log_file varchar(32) default NULL, log_pos int(11) default NULL, master_host varchar(60) NULL, master_log_file varchar(32) NULL, master_log_pos int NULL, PRIMARY KEY (host) );
Yo creé esa tabla en la base de datos mysql del Menéame. Así para el Menéame tengo el siguiente comando que se ejecuta cada madrugada:
mysqlhotcopy -q --flushlog --noindices --record_log_pos=mysql.log_pos
--addtodest mysql meneame /backups/hotcopy/
El comando anterior sólo tarda unos 6-10 segundos para copiar todos los datos de la base de datos, sin los índices y ocupando sólo 800 MB (el .sql comprimido si se usase mysqldump ocupa 1.5 GB).
La opción --noindices
indica que no copie los índices, ellos pueden ser luego regenerados con el mysqlcheck -rq
.
La opción --record-log_pos
es para indicar la base de datos y tabla dónde guardar la información del log del máster, es la que servirá para sincronizar las réplicas (en este caso le indico que copie las dos base de datos, mysql y meneame).
Los ficheros de backup se copiarán a /backups/hotcopy/mysql
y /backups/hotcopy/meneame
. En la tabla se guardarán datos como los siguientes:
| host | time_stamp | log_file | log_pos | ... +------------------+---------------------+------------------+---------+ | db.meneame.net | 2007-10-03 11:01:37 | mysql-bin.000634 | 98 |
Para [re] iniciar una réplica sólo hay que copiar esos ficheros a [por ejemplo] /var/lib/mysql/meneame
en el servidor correspondiente y:
- Detener el
slave
si está en marcha:slave stop;
- Mejor es detener también el mysql.
- Regenerar los índices con
mysqlcheck -qr /var/lib/mysql/meneame/*.MYI
- Poner el propietario adecuado: para Debian,
chown -R mysql.mysql /var/lib/mysql/meneame
también es mejor poner los permisos adecuados:
chmod 0660 /var/lib/mysql/meneame/*
- Arrancar el mysql e indicar el estado del máster (uso el ejemplo anterior):
CHANGE MASTER TO MASTER_HOST='tu.master.com', MASTER_USER='tu_usuario', MASTER_PASSWORD='tu_password', MASTER_LOG_FILE='mysql-bin.000634', MASTER_LOG_POS=98;
- Arrancar el slave:
SLAVE START
Ya está, con el comando sql show slave status
deberías ver como se sincroniza.
Creo que esta opción es la mejor porque además que la copia es rápida, si la haces cada día tienes siempre una “imagen” lista para ser usada para recuperar o iniciar cualquier otro slave sin necesidad de detener la base de datos en producción.
Nota: si harás réplicas de un máster tendrás que habilitar la “conexión a la red”, así que no te olvides de poner las iptables, definir qué direcciones IP pueden conectarse al puerto del mysql y poner claves a los usuarios habilitados para replicar. Sino podrías tener una importante fuga de datos
Add comment octubre 16th, 2014