El desarrollo de software implica a veces cambios que afectan al modelo de datos pero dichas modificaciones tienen una serie de problem谩ticas como la necesidad de hacer los cambios en linea o el tama帽o de los datos a reorganizar.
En este post quiero hablar sobre las herramientas existentes para el cambio de esquema de base de datos en MySQL, que limitaciones tienen dichas herramientas si se usa Galera
para la replicaci贸n y como he adaptado gh-ost
, la herramienta de cambios de esquema de GitHub, para poder usarlo con Galera
.
Cambios de esquemas
En MySQL es posible realizar cambios de base de datos de dos formas principalmente:
- Mediante la operaci贸n
ALTER
de MySQL; es la forma m谩s sencilla pero no permite pausar el proceso en caso de necesidad y exceptuando de ciertas operaciones, impide el uso concurrente de la tabla a modificar durante el proceso. - Mediante el uso de herramientas de terceros que permiten un mayor control del proceso aunque con ciertas restricciones. Algunas de estas herramientas pueden ser pt-osc, OnlineSchemaChange o gh-ost.
Dichos dos m茅todos son tambi茅n aplicables si se usa Galera
aunque, debido a que sigue un enfoque maestro-maestro, tiene algunas peculiaridades para aplicar cambios de base de datos, tanto mediante las operaciones proporcionadas por MySQL como por las herramientas de terceros.
Galera
Galera
es un plug-in para InnoDB que permite realizar una replicaci贸n virtualmente s铆ncrona multi-maestro. Este enfoque permite, a diferencia de la replicaci贸n normal as铆ncrona de MySQL, que todos los nodos del grupo tengan los mismos datos y, por tanto, realizar escrituras en cualquier nodo del grupo sacrificando algo de rendimiento en las escrituras.
Los cambios de esquema son operaciones especiales en Galera
, dado que modifican la base de datos y son no-transaccionales. Galera
cuenta con dos modos para aplicar cambios de base de datos mediante la operaci贸n ALTER
:
- TOI1 son cambios de esquema realizados en todos los nodos del grupo en la misma secuencia de orden total, evitando que otras transacciones se apliquen durante la operaci贸n.
- RSU2 son cambios de esquema que se ejecutan localmente, afectando s贸lo al nodo en el que se ejecutan. Los cambios no se replican al resto del grupo.
Estos dos modos presentan una serie de inconvenientes: las operaciones TOI impiden que otras transacciones se apliquen en todo el grupo durante el cambio de esquema mientras que las RSU pueden dejar el grupo en un estado inconsistente si el binary log en formato ROW
no es compatible entre esquemas.
Respecto al uso de herramientas de terceros, Galera
tiene una serie de limitaciones entre las que se encuentra el no soporte al bloqueo de tablas, operaci贸n necesaria en las herramientas OnlineSchemaChange
y gh-ost
para aplicar los 煤ltimos eventos debido a su naturaleza as铆ncrona, problema que no tiene pt-osc
debido a que los eventos son aplicados por la base de datos debido al uso de triggers.
A pesar que pt-osc
es compatible con Galera
, el uso de triggers presenta una serie de inconvenientes debido a que no es posible pausar por completo la operaci贸n en caso de necesidad y que el uso de triggers a帽aden una carga extra a la base de datos. Por ello, para permitir usar gh-ost
en Galera
, es necesario investigar por qu茅 necesita el uso de LOCK TABLES
y buscar un planteamiento alternativo.
gh-ost
gh-ost es la herramienta de GitHub para la aplicaci贸n de cambios de esquema en l铆nea y tiene interesantes ventajas respecto a otras herramientas existentes. Una de sus caracter铆sticas principales es que no usa triggers para sincronizar los cambios de la tabla original con la tabla fantasma3 si no los binlogs de MySQL y, por ello, permite verdaderamente parar totalmente la migraci贸n en caso de necesidad.
La raz贸n que impide usar gh-ost
con Galera
es que, para poder hacer la etapa de cut-over, gh-ost
hace uso de la instrucci贸n lock, instrucci贸n no est谩 soportada en Galera
.
Cut-over
En la documentaci贸n de gh-ost
la etapa de cut-over se define como the final major step of the migration
y su objetivo es reemplazar la tabla fantasma por la tabla original. Para dicho prop贸sito, es necesario que ambas tablas tengan aplicados los mismos registros a la hora de realizar el intercambio o, de lo contrario, se perder铆an datos en el proceso de migraci贸n.
A diferencia de otras herramientas de cambios de esquema en linea como pt-osc
, gh-ost
no delega en la base de datos la aplicaci贸n de los registros modificados durante la migraci贸n y, por ello, necesita bloquear moment谩neamente los cambios en la tabla original hasta que se apliquen todos los cambios pendientes del binlog, es ah铆 donde es necesario el uso de la operaci贸n lock en la tabla original.
LOCK TABLES
El primer enfoque que puede venir a la cabeza es que aunque la operaci贸n lock en Galera
no permite bloquear el acceso a una tabla en todos los nodos at贸micamente si que acepta bloquear los accesos de un nodo en particular, por lo que podr铆a ser posible aplicar el LOCK TABLES
manualmente en todos los nodos. Tras algo de investigaci贸n y un par de pruebas dicho enfoque queda descartado por varias razones:
- El algoritmo de cut-over at贸mico de
gh-ost
necesita el uso de varias conexiones independientes para funcionar y aunque garantiza dejar el grupo en un estado consistente en el caso de que ocurran errores en las conexiones, dicha premisa deja de ser cierta si se tiene que aplicar unLOCK TABLES
por cada nodo. Si quieres saber c贸mo funciona la estrategia de gh-ost para aplicar el cut-over at贸mico te recomiendo que leas el Issue #82. - Como se puede ver en MDEV-12647, es bastante probable dejar alguno de los nodos colgado al usar el
LOCK TABLES
en cada nodo.
Por ello el uso del LOCK TABLES
queda descartado y es necesario analizar otras soluciones existentes para la realizaci贸n de migraciones de esquema sin p茅rdida de servicio y que si permiten su uso con Galera
, es ah铆 donde entra en juego pt-osc
.
pt-osc
pt-osc es una herramienta de Percona que permite realizar migraciones de esquemas sin p茅rdida de servicio compatible con Galera
y que se basa en delegar en la base de datos la copia los datos modificados durante la migraci贸n mediante triggers, por lo que los cambios de la tabla original estan sincronizados con la tabla fantasma. Si quieres saber como asegura la consistencia te recomiendo que leas esta respuesta de StackExchange.
Soluci贸n planteada
Por lo tanto, si es posible realizar una migraci贸n consistente mediante triggers tal vez sea posible utilizarlos aunque solo sea para la etapa de cut-over. Para ello es posible plantear una nueva estrategia de cut-over cuyo procedimiento es el siguiente:
- A la hora de empezar el cut-over se inyecta un evento en el binlog para notificar a
gh-ost
de que deje de escribir los nuevos registros en la tabla fantasma pero que siga ley茅ndolos del binlog. - Una vez recibido el evento
gh-ost
deja de aplicar los eventos pero almacena los valores seg煤n la clave 煤nica usada durante la migraci贸n. - Se crean los triggers necesarios para sincronizar los nuevos registros entre la tabla original y la fantasma.
- Se inyecta un nuevo evento en el binlog para notificar que los triggers se han creado.
- Una vez recibido este segundo evento se dejan de leer el binlog y por consiguiente, tambi茅n de guardar los valores seg煤n la clave 煤nica.
- Los registros ocurridos entre ambos eventos pueden ser inconsistentes dado que ha dejado de aplicarse los eventos del binlog. Para solucionar dicho problema se realiza una etapa de saneamiento que consiste en eliminarlos de la tabla fantasma si existen e insertarlos de nuevo desde la tabla original.
- Una vez se haya saneado los eventos, ambas tablas son consistentes, por lo que es posible usar la operaci贸n
RENAME TABLE
para intercambiar la tabla original con la fantasma de una manera at贸mica. - Tras dicha operaci贸n o en el caso de fallo se eliminan los triggers.
Resultados y conclusi贸n
Una vez planteada una soluci贸n he implementado los cambios necesarios el c贸digo de gh-ost
y despu茅s de un par de semanas de pruebas hemos empezado a usarlo en producci贸n con unos muy buenos resultados, por lo que he creado la pull request #780.
Respecto a la conclusi贸n, aunque gh-ost
se considere triggerless, la vida de los triggers necesarios ser谩 igual a lo que tarde en aplicarse los cambios pendientes del binlog y sanear las entradas que puedan ser inconsistentes, que ser谩 de apenas unos segundos en el peor de los casos, por lo que se considera aceptable.