How to Configure MySQL Group Replication on RHEL 7
MySQL Group Replication, introduced in MySQL 5.7.17, is a plugin-based high-availability mechanism that enables a set of MySQL servers to form a replication group where all writes are coordinated through a distributed consensus algorithm (Paxos-based). Unlike classic primary-replica replication, Group Replication provides built-in automatic failover: if the primary node fails, the remaining members elect a new primary without manual intervention. The group can operate in single-primary mode (only one member accepts writes at a time) or multi-primary mode (all members accept writes simultaneously). This tutorial configures a three-node Group Replication cluster in single-primary mode on RHEL 7.
Prerequisites
- Three RHEL 7 servers:
db1(192.168.1.10),db2(192.168.1.11),db3(192.168.1.12) - MySQL 5.7.17 or later installed on all three servers
- All nodes able to reach each other on port 3306 (MySQL) and port 33061 (Group Replication communication)
- Identical MySQL versions on all nodes (strongly recommended)
- Root or sudo access on all nodes
- Unique hostnames or IP addresses for each node
Step 1: Verify MySQL Version
Group Replication requires MySQL 5.7.17 as a minimum. Verify on each node:
mysql --version
If you need to install or upgrade MySQL 5.7 from the official MySQL Yum repository:
sudo yum install -y https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
sudo yum install -y mysql-community-server
sudo systemctl start mysqld
sudo systemctl enable mysqld
Retrieve the temporary root password generated at first start:
sudo grep 'temporary password' /var/log/mysqld.log
Step 2: Configure /etc/my.cnf on All Three Nodes
Group Replication relies on GTID-based replication and requires several specific settings. The configuration differs only in the server-id, report_host, and the node’s own entry in group_replication_local_address.
On db1 (192.168.1.10):
sudo vi /etc/my.cnf
[mysqld]
# --- Basic settings ---
server-id = 1
report_host = 192.168.1.10
bind-address = 0.0.0.0
# --- GTID ---
gtid_mode = ON
enforce_gtid_consistency = ON
# --- Binary log ---
log-bin = mysql-bin
log_slave_updates = ON
binlog_format = ROW
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
# --- Group Replication plugin ---
plugin_load_add = group_replication.so
group_replication_group_name = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
group_replication_start_on_boot = OFF
group_replication_local_address = "192.168.1.10:33061"
group_replication_group_seeds = "192.168.1.10:33061,192.168.1.11:33061,192.168.1.12:33061"
group_replication_bootstrap_group = OFF
Replace aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee with a real UUID. You can generate one with:
python -c "import uuid; print(uuid.uuid4())"
Use the same UUID on all three nodes — it identifies the group.
On db2 (192.168.1.11), use server-id = 2, report_host = 192.168.1.11, and group_replication_local_address = "192.168.1.11:33061". All other group settings are identical.
On db3 (192.168.1.12), use server-id = 3, report_host = 192.168.1.12, and group_replication_local_address = "192.168.1.12:33061".
Restart MySQL on all nodes after editing my.cnf:
sudo systemctl restart mysqld
Step 3: Create the Replication User on All Nodes
Group Replication requires a dedicated user for internal distributed recovery. Create it on each node. Because binary logging is on, disable logging just for this statement to prevent the user creation from being replicated via binary log (it will be provisioned via Group Replication’s own recovery instead):
mysql -u root -p
SET SQL_LOG_BIN=0;
CREATE USER 'gr_user'@'%' IDENTIFIED BY 'GrPassw0rd!';
GRANT REPLICATION SLAVE ON *.* TO 'gr_user'@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
Step 4: Install the Group Replication Plugin
Because plugin_load_add = group_replication.so is set in my.cnf, the plugin loads automatically at startup. Verify it loaded on each node:
SHOW PLUGINSG
Look for a line containing group_replication with Status: ACTIVE. If the plugin did not load, install it manually:
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Step 5: Configure the Replication Channel Credentials
Tell the Group Replication plugin which credentials to use for distributed recovery on each node:
CHANGE MASTER TO MASTER_USER='gr_user', MASTER_PASSWORD='GrPassw0rd!'
FOR CHANNEL 'group_replication_recovery';
Step 6: Bootstrap the Group from db1
The group must be bootstrapped by exactly one node — the first node to start the group. Enable bootstrapping temporarily on db1 only, start Group Replication, then immediately disable bootstrapping:
-- On db1 only
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
Verify db1 has joined and is the primary:
SELECT * FROM performance_schema.replication_group_membersG
You should see one member with MEMBER_STATE = ONLINE and MEMBER_ROLE = PRIMARY.
Step 7: Add db2 and db3 to the Group
On db2 and db3 (do NOT set bootstrap_group=ON — that is only for the first node):
START GROUP_REPLICATION;
Each node will use Group Replication’s distributed recovery to synchronize its data with the existing group members before going ONLINE. Check the group membership again on any node:
SELECT MEMBER_ID, MEMBER_HOST, MEMBER_PORT, MEMBER_STATE, MEMBER_ROLE
FROM performance_schema.replication_group_members;
Expected output with all three nodes online:
+--------------------------------------+--------------+-------------+--------------+-------------+
| MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE |
+--------------------------------------+--------------+-------------+--------------+-------------+
| a1b2c3d4-... | 192.168.1.10 | 3306 | ONLINE | PRIMARY |
| e5f6a7b8-... | 192.168.1.11 | 3306 | ONLINE | SECONDARY |
| c9d0e1f2-... | 192.168.1.12 | 3306 | ONLINE | SECONDARY |
+--------------------------------------+--------------+-------------+--------------+-------------+
Step 8: Single-Primary vs Multi-Primary Mode
By default, Group Replication starts in single-primary mode where only the PRIMARY accepts writes and the SECONDARY members are read-only. To switch to multi-primary mode (all nodes accept writes — useful for write-scale-out, but requires application-level conflict handling), use the UDF available in MySQL 5.7.20+:
-- Switch to multi-primary mode (run on any member)
SELECT group_replication_switch_to_multi_primary_mode();
-- Switch back to single-primary mode
SELECT group_replication_switch_to_single_primary_mode();
In multi-primary mode, all nodes have MEMBER_ROLE = PRIMARY. Note that multi-primary mode does not prevent write conflicts at the application level — your application must either shard writes or be designed to tolerate optimistic concurrency failures.
Step 9: Open Firewall Ports for Group Communication
Group Replication uses port 33061 for its internal GCS (Group Communication System) communication in addition to the standard MySQL port 3306. Open both on all nodes:
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --permanent --add-port=33061/tcp
sudo firewall-cmd --reload
Step 10: Auto-Start Group Replication on Boot
To have nodes automatically rejoin the group after a reboot, set group_replication_start_on_boot = ON in /etc/my.cnf. After the initial bootstrap is complete and the group is stable this is safe to enable:
group_replication_start_on_boot = ON
Do not set group_replication_bootstrap_group = ON in the file permanently — bootstrapping must only happen once when forming a brand-new group.
MySQL Group Replication on RHEL 7 provides a robust, built-in high-availability solution for MySQL 5.7.17 and above. The combination of GTID-based replication, the Paxos consensus algorithm, and automatic primary election eliminates the need for external tools to handle failover. The three key configuration areas — the group UUID, per-node addresses in group_replication_local_address, and the group seeds list — must be consistent across all members. Once the group is stable, connect an application-layer proxy such as MySQL Router or ProxySQL in front of the group to transparently route writes to the current primary and reads to secondaries.