--- title: "Cómo configurar MySQL Group Replication en Ubuntu 24.04" description: "Configura MySQL Group Replication con tres nodos en Ubuntu 24.04 en modo primario único con failover automático, cambio de primario y altas y bajas de miembros." category: "Base de Datos Avanzada" language: es source: https://cubepath.com/es/docs/base-de-datos-avanzada/configuracion-de-replicacion-de-grupos-mysql updated: 2026-09-25 --- # Cómo configurar MySQL Group Replication en Ubuntu 24.04 MySQL Group Replication es el mecanismo de alta disponibilidad integrado en MySQL. Varios servidores forman un grupo que acuerda el orden de cada transacción mediante un protocolo de consenso, de modo que todos aplican los mismos cambios en el mismo orden. En modo primario único, un miembro acepta escrituras y el resto son réplicas de solo lectura; si el primario cae, el grupo elige otro automáticamente. En este tutorial configurarás un grupo de tres nodos con MySQL 8.0 desde los repositorios de Ubuntu 24.04, en modo primario único. Comprobarás la replicación, provocarás un failover, cambiarás el primario a mano y verás cómo añadir y retirar miembros. ## Requisitos previos - Tres servidores con Ubuntu 24.04 LTS, por ejemplo VPS de CubePath, con al menos 2 GB de RAM y un usuario no root con `sudo`. - Red privada con baja latencia entre ellos. Cada transacción necesita el acuerdo de la mayoría del grupo antes de confirmarse. - Tres miembros como mínimo (el grupo tolera la caída de uno) y nueve como máximo. Valores usados en los ejemplos: | Nodo | IP privada | |---|---| | `mysql1` | `10.0.0.11` | | `mysql2` | `10.0.0.12` | | `mysql3` | `10.0.0.13` | Puertos entre nodos: | Puerto | Uso | |---|---| | 3306/tcp | Clientes y recuperación de datos entre miembros | | 33061/tcp | Comunicación interna del grupo | ## Paso 1: Instalar MySQL en los tres nodos Ejecuta en **cada nodo**: ```bash sudo apt update sudo apt install mysql-server ``` Comprueba la versión y que el plugin de Group Replication está disponible: ```bash mysql --version ls /usr/lib/mysql/plugin/group_replication.so ``` ```output mysql Ver 8.0.43-0ubuntu0.24.04.1 for Linux on x86_64 ((Ubuntu)) /usr/lib/mysql/plugin/group_replication.so ``` Abre los puertos solo para la red privada: ```bash sudo ufw allow from 10.0.0.0/24 to any port 3306,33061 proto tcp ``` ## Paso 2: Configurar cada servidor para Group Replication Genera un UUID que identificará al grupo. Hazlo **una sola vez** y usa el mismo valor en los tres nodos: ```bash cat /proc/sys/kernel/random/uuid ``` ```output aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee ``` MySQL en Ubuntu lee los ficheros de `/etc/mysql/mysql.conf.d/` en orden alfabético, y los posteriores prevalecen. Crea un fichero que se cargue después de `mysqld.cnf` para que su `bind-address` sustituya al valor por defecto (`127.0.0.1`). En **mysql1**: ```bash sudo nano /etc/mysql/mysql.conf.d/zz-group-replication.cnf ``` ```ini [mysqld] # Identidad del servidor server_id = 1 bind-address = 0.0.0.0 report_host = 10.0.0.11 # Requisitos de Group Replication gtid_mode = ON enforce_gtid_consistency = ON disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" # Plugin y grupo plugin_load_add = group_replication.so group_replication_group_name = "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee" group_replication_start_on_boot = OFF group_replication_local_address = "10.0.0.11:33061" group_replication_group_seeds = "10.0.0.11:33061,10.0.0.12:33061,10.0.0.13:33061" group_replication_bootstrap_group = OFF # Cifrado del tráfico del grupo y de la recuperación group_replication_ssl_mode = REQUIRED group_replication_recovery_use_ssl = ON ``` Qué hace cada bloque: - `server_id` debe ser distinto en cada nodo. `report_host` es la dirección con la que el miembro se anuncia al resto; usar la IP evita depender de la resolución de nombres. - Group Replication exige GTID e InnoDB. `disabled_storage_engines` impide crear por error tablas en motores que no se replican. El log binario, el formato `ROW` y `log_replica_updates` ya vienen activos por defecto en MySQL 8.0. - `group_replication_group_seeds` son los miembros a los que un nodo intenta conectarse para unirse. `group_replication_local_address` es la dirección de este nodo para la comunicación interna (puerto 33061, distinto del 3306). - `group_replication_start_on_boot = OFF` evita que el nodo intente unirse antes de que el grupo exista. Lo activarás en el paso 7. - Las dos opciones de SSL usan los certificados que MySQL genera automáticamente al instalarse, suficiente para cifrar el tráfico dentro de una red privada. En **mysql2** y **mysql3** crea el mismo fichero cambiando solo estas tres líneas: ```ini # En mysql2 server_id = 2 report_host = 10.0.0.12 group_replication_local_address = "10.0.0.12:33061" ``` ```ini # En mysql3 server_id = 3 report_host = 10.0.0.13 group_replication_local_address = "10.0.0.13:33061" ``` Reinicia MySQL en **cada nodo** y comprueba que el plugin está activo: ```bash sudo systemctl restart mysql sudo mysql -e "SELECT PLUGIN_NAME, PLUGIN_STATUS FROM information_schema.PLUGINS WHERE PLUGIN_NAME = 'group_replication';" ``` ```output +-------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +-------------------+---------------+ | group_replication | ACTIVE | +-------------------+---------------+ ``` ## Paso 3: Crear el usuario de recuperación Cuando un miembro se une, copia de otro las transacciones que le faltan a través del canal `group_replication_recovery`, con un usuario de replicación. Créalo en **cada nodo** con el log binario desactivado para esta sesión, de modo que la creación del usuario no genere transacciones locales distintas en cada servidor: ```bash sudo mysql ``` ```sql SET SQL_LOG_BIN = 0; CREATE USER 'rpl_user'@'%' IDENTIFIED BY 'your_strong_password'; GRANT REPLICATION SLAVE, CONNECTION_ADMIN, BACKUP_ADMIN, GROUP_REPLICATION_STREAM ON *.* TO 'rpl_user'@'%'; SET SQL_LOG_BIN = 1; CHANGE REPLICATION SOURCE TO SOURCE_USER = 'rpl_user', SOURCE_PASSWORD = 'your_strong_password' FOR CHANNEL 'group_replication_recovery'; EXIT; ``` Usa la misma contraseña en los tres nodos y sustituye `your_strong_password` por una segura. ## Paso 4: Arrancar el grupo en el primer nodo El primer miembro debe crear el grupo (bootstrap). Esto se hace **solo en un nodo** y **solo una vez**; después se desactiva para que no pueda crear un segundo grupo por accidente. En **mysql1**: ```bash sudo mysql ``` ```sql SET GLOBAL group_replication_bootstrap_group = ON; START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group = OFF; SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members; ``` ```output +-------------+--------------+-------------+ | MEMBER_HOST | MEMBER_STATE | MEMBER_ROLE | +-------------+--------------+-------------+ | 10.0.0.11 | ONLINE | PRIMARY | +-------------+--------------+-------------+ ``` ## Paso 5: Unir los otros dos nodos En **mysql2** y después en **mysql3**: ```bash sudo mysql -e "START GROUP_REPLICATION;" ``` El nodo pasa por el estado `RECOVERING` mientras copia las transacciones que le faltan y después queda `ONLINE`. Comprueba el grupo desde cualquier miembro: ```bash sudo mysql -e "SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;" ``` ```output +-------------+--------------+-------------+ | MEMBER_HOST | MEMBER_STATE | MEMBER_ROLE | +-------------+--------------+-------------+ | 10.0.0.11 | ONLINE | PRIMARY | | 10.0.0.12 | ONLINE | SECONDARY | | 10.0.0.13 | ONLINE | SECONDARY | +-------------+--------------+-------------+ ``` ## Paso 6: Probar la replicación En el primario (**mysql1**), crea una base de datos y una tabla. Group Replication exige que todas las tablas tengan clave primaria: ```bash sudo mysql -e "CREATE DATABASE gr_test; CREATE TABLE gr_test.t (id INT PRIMARY KEY, origen VARCHAR(20)); INSERT INTO gr_test.t VALUES (1, 'mysql1');" ``` Léela en un secundario (**mysql3**): ```bash sudo mysql -e "SELECT * FROM gr_test.t;" ``` ```output +----+--------+ | id | origen | +----+--------+ | 1 | mysql1 | +----+--------+ ``` Intenta escribir en el secundario. Debe fallar, porque en modo primario único los secundarios se ponen en `super_read_only`: ```bash sudo mysql -e "INSERT INTO gr_test.t VALUES (2, 'mysql3');" ``` ```output ERROR 1290 (HY000) at line 1: The MySQL server is running with the --super-read-only option so it cannot execute this statement ``` ## Paso 7: Unirse automáticamente al arrancar Ahora que el grupo existe, activa `group_replication_start_on_boot` para que un nodo que se reinicie vuelva a unirse solo. En **cada nodo**, cambia la línea en `/etc/mysql/mysql.conf.d/zz-group-replication.cnf`: ```ini group_replication_start_on_boot = ON ``` El cambio se aplicará en el próximo reinicio de cada nodo; no hace falta reiniciar ahora. > Importante: si los tres nodos se paran a la vez, ninguno encontrará un grupo al que unirse. En ese caso hay que repetir el bootstrap del paso 4 en el nodo con más transacciones aplicadas (compara `SELECT @@GLOBAL.gtid_executed;` en cada uno) y después arrancar Group Replication en los demás. ## Paso 8: Probar el failover automático Para MySQL en el primario (**mysql1**): ```bash sudo systemctl stop mysql ``` Desde **mysql2**, comprueba el grupo. En pocos segundos uno de los secundarios pasa a primario: ```bash sudo mysql -e "SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;" ``` ```output +-------------+--------------+-------------+ | MEMBER_HOST | MEMBER_STATE | MEMBER_ROLE | +-------------+--------------+-------------+ | 10.0.0.12 | ONLINE | PRIMARY | | 10.0.0.13 | ONLINE | SECONDARY | +-------------+--------------+-------------+ ``` El nuevo primario desactiva `super_read_only` y acepta escrituras. Vuelve a arrancar MySQL en **mysql1**: ```bash sudo systemctl start mysql ``` Con `group_replication_start_on_boot = ON`, se une de nuevo como `SECONDARY` y recupera las transacciones que se perdió. ## Paso 9: Cambiar el primario y gestionar miembros Para devolver el rol de primario a mysql1 (por ejemplo, porque tiene más recursos), obtén su UUID de miembro: ```bash sudo mysql -e "SELECT MEMBER_ID, MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;" ``` Y ejecuta desde cualquier miembro, con el `MEMBER_ID` de mysql1: ```bash sudo mysql -e "SELECT group_replication_set_as_primary('member_id_de_mysql1');" ``` Para retirar un miembro de forma ordenada (por ejemplo, antes de actualizarlo), ejecuta en ese nodo: ```bash sudo mysql -e "STOP GROUP_REPLICATION;" ``` El resto del grupo sigue funcionando. Cuando termines, vuelve a unirlo con `START GROUP_REPLICATION;`. Para añadir un cuarto nodo, repite los pasos 1 a 3 en él con un `server_id` nuevo, añade su dirección a `group_replication_group_seeds` en todos los nodos y ejecuta `START GROUP_REPLICATION;`. > Nota: el modo multiprimario, en el que todos los miembros aceptan escrituras, se activa con `SELECT group_replication_switch_to_multi_primary_mode();`. Implica conflictos de certificación cuando dos miembros modifican la misma fila y restricciones adicionales (por ejemplo, con claves foráneas en cascada), así que el modo primario único es la opción recomendada para la mayoría de aplicaciones. ## Paso 10: Monitorizar el grupo Además del estado de los miembros, `performance_schema.replication_group_member_stats` muestra si algún nodo acumula transacciones pendientes de aplicar o de certificar: ```bash sudo mysql -e "SELECT MEMBER_ID, COUNT_TRANSACTIONS_IN_QUEUE, COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE, COUNT_CONFLICTS_DETECTED FROM performance_schema.replication_group_member_stats\G" ``` Valores de cola que crecen de forma sostenida indican que un miembro va más lento que el resto. Si se retrasa demasiado, el control de flujo del grupo frena las escrituras en el primario para que pueda alcanzarlo. ## Solución de problemas **`This member has more executed transactions than those present in the group`**: el nodo tiene transacciones locales que el grupo no conoce, normalmente por crear usuarios o bases de datos sin `SET SQL_LOG_BIN = 0`. En un nodo recién instalado y sin datos propios, puedes limpiar su historial GTID con `RESET MASTER;` y volver a ejecutar `START GROUP_REPLICATION;`. No lo hagas en un nodo con datos que no existan en el grupo. **El nodo se queda en `RECOVERING` o pasa a `ERROR`**: revisa el log de errores con `sudo tail -n 50 /var/log/mysql/error.log`. Las causas habituales son credenciales incorrectas en el canal `group_replication_recovery`, el puerto 3306 cerrado entre nodos o un `report_host` al que los demás no llegan. **`START GROUP_REPLICATION` falla con errores de conexión al puerto 33061**: comprueba el firewall y que `group_replication_local_address` usa la IP de ese nodo. Por defecto, MySQL solo acepta miembros desde redes privadas (`group_replication_ip_allowlist = AUTOMATIC`); si tus nodos usan IP públicas, define esa variable con las direcciones de los miembros. **Error al crear tablas sin clave primaria**: Group Replication rechaza las tablas InnoDB sin clave primaria o única no nula. Añade una clave primaria a la tabla. ## Conclusión Tienes un grupo MySQL de tres nodos en Ubuntu 24.04 en modo primario único, con tráfico cifrado entre miembros, failover automático y los procedimientos para cambiar el primario y retirar o añadir nodos. Como siguientes pasos puedes: - Instalar MySQL Router delante del grupo para que las aplicaciones se conecten siempre al primario actual sin cambiar su configuración. - Programar copias de seguridad desde un secundario con `mysqldump --single-transaction` o Percona XtraBackup. - Añadir alertas sobre los miembros que no estén `ONLINE` y sobre el crecimiento de las colas de transacciones.