Home Database MySQL InnoDB Cluster: High Availability Setup Guide
Advanced 3 min · July 13, 2026

MySQL InnoDB Cluster: High Availability Setup Guide

Learn to set up MySQL InnoDB Cluster for high availability.

N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Notes here come from systems that actually shipped.

Follow
Production
production tested
July 13, 2026
last updated
2,165
articles · all by Naren
Before you start⏱ 20-25 min read
  • Basic knowledge of MySQL administration (starting/stopping, configuration files).
  • Familiarity with SQL and database concepts.
  • Three or more MySQL 8.0+ instances (physical or virtual).
  • MySQL Shell installed on an admin machine.
  • Network connectivity between nodes on ports 3306 and 33061.
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • InnoDB Cluster provides automatic failover and high availability for MySQL.
  • It uses Group Replication for data consistency across nodes.
  • Setup involves configuring instances, creating a cluster, and adding nodes.
  • MySQL Router provides transparent client routing.
  • Monitor with performance_schema and cluster status commands.
✦ Definition~90s read
What is MySQL InnoDB Cluster?

MySQL InnoDB Cluster is a high-availability solution that combines Group Replication, MySQL Shell, and MySQL Router to provide automatic failover and transparent client routing for MySQL databases.

Think of InnoDB Cluster as a team of synchronized dancers.
Plain-English First

Think of InnoDB Cluster as a team of synchronized dancers. Each dancer (MySQL instance) knows the exact same moves (data). If one dancer stumbles (node fails), the others seamlessly continue the performance without missing a beat. The audience (your application) doesn't even notice the change because the show goes on.

Imagine your e-commerce platform is experiencing a surge in traffic during a flash sale. Suddenly, your primary database server crashes. Without high availability, your site goes down, orders are lost, and customers are furious. This is where MySQL InnoDB Cluster comes to the rescue. It's a built-in solution that provides automatic failover, ensuring your database remains accessible even when individual nodes fail. InnoDB Cluster combines Group Replication for data consistency, MySQL Shell for management, and MySQL Router for client routing. In this tutorial, you'll learn how to set up a three-node InnoDB Cluster from scratch, configure MySQL Router, and handle real-world scenarios like node failures and recovery. By the end, you'll have a production-ready high-availability setup that keeps your applications running smoothly.

Prerequisites and Environment Setup

Before setting up InnoDB Cluster, ensure you have three MySQL 8.0+ instances (physical or virtual machines) with clean installations. Each instance should have a unique server_id and be able to communicate over ports 3306 (MySQL) and 33061 (Group Replication). Install MySQL Shell on your admin machine. For this tutorial, we'll use three nodes: node1 (192.168.1.10), node2 (192.168.1.11), node3 (192.168.1.12). Configure each MySQL instance with the following minimal settings in my.cnf:

[mysqld] server_id=1 # unique per node gtid_mode=ON enforce_gtid_consistency=ON binlog_format=ROW log_bin=mysql-bin log_slave_updates=ON relay_log=relay-log

group_replication=ON group_replication_start_on_boot=OFF group_replication_group_name='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' 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'

Restart MySQL after changes.

my.cnfBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
# On node1 (192.168.1.10)
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_format=ROW
log_bin=mysql-bin
log_slave_updates=ON
relay_log=relay-log
group_replication=ON
group_replication_start_on_boot=OFF
group_replication_group_name='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
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'
⚠ Firewall Configuration
📊 Production Insight
In production, use a configuration management tool like Ansible to ensure consistency across nodes.
🎯 Key Takeaway
Proper configuration of each MySQL instance is critical. Use unique server_ids and ensure GTID mode is enabled.

Creating the InnoDB Cluster

Once the instances are configured, use MySQL Shell to create the cluster. Connect to the first node (node1) using MySQL Shell:

mysqlsh --uri root@192.168.1.10:3306

var cluster = dba.createCluster('myCluster');

This command configures Group Replication on node1 and bootstraps the cluster. After creation, check the status:

cluster.status();

You should see node1 as the PRIMARY (read-write) and the cluster is ONLINE. Now add the other nodes:

cluster.addInstance('root@192.168.1.11:3306'); cluster.addInstance('root@192.168.1.12:3306');

Each addition will prompt for the root password and then synchronize the data from the primary. After adding all nodes, the cluster.status() should show all three nodes as ONLINE with one PRIMARY and two SECONDARIES.

create_cluster.jsBASH
1
2
3
4
5
6
7
8
9
10
11
# Connect to node1
mysqlsh --uri root@192.168.1.10:3306

# Inside MySQL Shell
var cluster = dba.createCluster('myCluster');
cluster.status();

# Add node2 and node3
cluster.addInstance('root@192.168.1.11:3306');
cluster.addInstance('root@192.168.1.12:3306');
cluster.status();
Output
{
"clusterName": "myCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "192.168.1.10:3306",
"ssl": "REQUIRED",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"192.168.1.10:3306": {
"address": "192.168.1.10:3306",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.32"
},
"192.168.1.11:3306": {
"address": "192.168.1.11:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.32"
},
"192.168.1.12:3306": {
"address": "192.168.1.12:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.32"
}
}
},
"groupInformationSourceMember": "192.168.1.10:3306"
}
💡Recovery Method
📊 Production Insight
In production, use a dedicated admin user with appropriate privileges for cluster management.
🎯 Key Takeaway
Use dba.createCluster() to bootstrap and cluster.addInstance() to add nodes. Always verify with cluster.status().

Configuring MySQL Router

MySQL Router provides transparent client-side routing. Install MySQL Router on a separate machine (or on the application server). Configure it to connect to the cluster:

mysqlrouter --bootstrap root@192.168.1.10:3306 --user=mysqlrouter

This command discovers the cluster and creates configuration files. The default configuration creates two ports: 6446 (read-write, routed to primary) and 6447 (read-only, load-balanced across secondaries). Start the router:

systemctl start mysqlrouter

Now applications can connect to port 6446 for writes and 6447 for reads. If the primary fails, Router automatically routes to the new primary. Test the connection:

mysql -h 127.0.0.1 -P 6446 -u appuser -p

mysqlrouter --list-routes

router_setup.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
# Install MySQL Router (example on Ubuntu)
sudo apt-get install mysql-router

# Bootstrap the router
sudo mysqlrouter --bootstrap root@192.168.1.10:3306 --user=mysqlrouter

# Start the router
sudo systemctl start mysqlrouter
sudo systemctl enable mysqlrouter

# Test connection
mysql -h 127.0.0.1 -P 6446 -u appuser -p
Output
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.32 MySQL Community Server - GPL
mysql> SELECT @@hostname;
+------------+
| @@hostname |
+------------+
| node1 |
+------------+
1 row in set (0.00 sec)
🔥Router High Availability
📊 Production Insight
Use a dedicated user for Router bootstrap with minimal privileges (CREATE USER, SELECT on performance_schema).
🎯 Key Takeaway
MySQL Router simplifies client connections by providing fixed ports that automatically route to the correct cluster node.

Testing Failover and Recovery

Simulate a primary failure to verify automatic failover. First, identify the primary:

mysqlsh -- cluster.status()

sudo systemctl stop mysql

After a few seconds, check cluster status again. You should see that one of the secondaries (e.g., node2) has become the new primary. The cluster status will show 'OK' with a new primary. Applications connected via Router will experience a brief interruption (usually a few seconds) but will automatically reconnect. To recover the failed node, start MySQL on node1 and rejoin it to the cluster:

sudo systemctl start mysql mysqlsh -- cluster.rejoinInstance('root@192.168.1.10:3306')

After rejoining, node1 will become a secondary. Verify with cluster.status().

failover_test.shBASH
1
2
3
4
5
6
7
8
9
# On node1 (primary)
sudo systemctl stop mysql

# On admin machine, check cluster status
mysqlsh --uri root@192.168.1.11:3306 -e "cluster = dba.getCluster(); print(cluster.status())"

# Recover node1
sudo systemctl start mysql
mysqlsh --uri root@192.168.1.11:3306 -e "cluster = dba.getCluster(); cluster.rejoinInstance('root@192.168.1.10:3306')"
Output
{
"clusterName": "myCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "192.168.1.11:3306",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"192.168.1.11:3306": {
"address": "192.168.1.11:3306",
"mode": "R/W",
"role": "HA",
"status": "ONLINE"
},
"192.168.1.12:3306": {
"address": "192.168.1.12:3306",
"mode": "R/O",
"role": "HA",
"status": "ONLINE"
},
"192.168.1.10:3306": {
"address": "192.168.1.10:3306",
"mode": "R/O",
"role": "HA",
"status": "ONLINE"
}
}
}
}
⚠ Quorum Requirement
📊 Production Insight
Test failover regularly in a staging environment. Monitor the time it takes for Router to detect the new primary.
🎯 Key Takeaway
Automatic failover works when a majority of nodes are available. Always have an odd number of nodes to avoid split-brain.

Monitoring and Maintenance

Monitor cluster health using MySQL Shell and performance_schema. Key commands:

  • cluster.status(): Overall cluster health.
  • cluster.describe(): Configuration details.
  • SELECT * FROM performance_schema.replication_group_members: Member states.
  • SELECT * FROM performance_schema.replication_group_member_stats: Transaction stats.

Set up alerts for member state changes and replication lag. Use MySQL Enterprise Monitor or open-source tools like Prometheus with mysqld_exporter. Regular maintenance includes: - Upgrading MySQL versions: Use cluster rolling upgrade procedure. - Adding/removing nodes: Use cluster.addInstance() and cluster.removeInstance(). - Backup: Use mysqldump or MySQL Enterprise Backup. Remember that backups should be taken from a secondary to avoid load on primary.

monitoring.sqlSQL
1
2
3
4
5
6
7
8
9
-- Check member states
SELECT * FROM performance_schema.replication_group_members;

-- Check transaction statistics
SELECT * FROM performance_schema.replication_group_member_stats\G

-- Check replication lag
SELECT MEMBER_ID, COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE AS lag
FROM performance_schema.replication_group_member_stats;
Output
*************************** 1. row ***************************
CHANNEL_NAME: group_replication_applier
GROUP_NAME: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
MEMBER_ID: 12345678-1234-1234-1234-123456789012
MEMBER_HOST: node1
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.32
MEMBER_COMMUNICATION_STACK: XCom
*************************** 2. row ***************************
...
-- Lag query result
+--------------------------------------+------+
| MEMBER_ID | lag |
+--------------------------------------+------+
| 12345678-1234-1234-1234-123456789012 | 0 |
| 87654321-4321-4321-4321-210987654321 | 0 |
| 11223344-5566-7788-99aa-bbccddeeff00 | 0 |
+--------------------------------------+------+
💡Performance Schema
📊 Production Insight
Set up automated alerts for member state changes and replication lag exceeding thresholds (e.g., 10 seconds).
🎯 Key Takeaway
Regular monitoring of member states and replication lag is essential for cluster health. Use performance_schema for detailed metrics.

Scaling and Advanced Configuration

InnoDB Cluster supports scaling out by adding more secondary nodes for read scalability. However, adding too many nodes can increase replication lag. For write scaling, consider sharding with MySQL Cluster (NDB). Advanced configuration options include: - group_replication_flow_control_mode: Controls how aggressively to throttle writes to prevent lag. Set to 'QUOTA' for strict control. - group_replication_member_expel_timeout: Timeout for expelling unresponsive members. Increase to 30-60 seconds in production. - group_replication_autorejoin_tries: Number of automatic rejoin attempts.

You can also configure multi-primary mode (all nodes writable) but it requires conflict detection and is not recommended for most applications. To enable multi-primary:

var cluster = dba.createCluster('myCluster', {multiPrimary: true});

But be aware of potential conflicts and performance overhead.

advanced_config.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
-- Set flow control mode
SET GLOBAL group_replication_flow_control_mode = 'QUOTA';

-- Increase expel timeout
SET GLOBAL group_replication_member_expel_timeout = 30;

-- Enable auto-rejoin (up to 3 attempts)
SET GLOBAL group_replication_autorejoin_tries = 3;

-- Check current settings
SHOW VARIABLES LIKE 'group_replication%';
Output
+----------------------------------------------+-------+
| Variable_name | Value |
+----------------------------------------------+-------+
| group_replication_flow_control_mode | QUOTA |
| group_replication_member_expel_timeout | 30 |
| group_replication_autorejoin_tries | 3 |
| ... | ... |
+----------------------------------------------+-------+
🔥Multi-Primary Considerations
📊 Production Insight
Start with single-primary mode. Only consider multi-primary if you have a strong understanding of conflict resolution and your application can tolerate it.
🎯 Key Takeaway
Tune group_replication parameters for your workload. Multi-primary mode is advanced and requires careful planning.
● Production incidentPOST-MORTEMseverity: high

The Black Friday Outage: A Replication Nightmare

Symptom
During Black Friday, the primary database became unresponsive. The application timed out and users saw '500 Internal Server Error'.
Assumption
The developer assumed the primary was overloaded and tried to manually failover to a replica, but the replica was not in sync.
Root cause
The Group Replication member timeout was set too low (5 seconds). Under heavy load, a temporary network spike caused the primary to be expelled from the group, but the remaining nodes couldn't form a quorum due to a split-brain scenario.
Fix
Increased group_replication_member_expel_timeout to 30 seconds and added a third node to ensure quorum. Also implemented a health check script that automatically re-joins expelled members.
Key lesson
  • Always set group_replication_member_expel_timeout high enough to handle transient network issues.
  • Use an odd number of nodes (at least 3) to avoid split-brain.
  • Monitor cluster status with performance_schema and alerts.
  • Test failover scenarios regularly in a staging environment.
  • Document recovery procedures and train the team.
Production debug guideSymptom to Action4 entries
Symptom · 01
Application cannot connect to database; MySQL Router returns 'no available servers'.
Fix
Check cluster status: mysqlsh -- cluster.status(). Verify all nodes are ONLINE. Check MySQL Router logs for routing failures.
Symptom · 02
Node is in RECOVERING state for too long.
Fix
Check recovery progress: SELECT * FROM performance_schema.replication_group_member_stats. Ensure network connectivity and that the donor node has enough resources.
Symptom · 03
Quorum lost; cluster becomes read-only.
Fix
Identify the node with the most recent data and force it as primary: cluster.forceQuorumUsingPartitionOf(instance). Then re-add other nodes.
Symptom · 04
High latency on writes.
Fix
Check group replication lag: SELECT * FROM performance_schema.replication_group_member_stats. Tune group_replication_flow_control_mode or increase bandwidth.
★ Quick Debug Cheat SheetCommon symptoms and immediate actions for InnoDB Cluster issues.
Cluster not forming
Immediate action
Check firewall and ports (3306, 33061). Ensure all nodes can communicate.
Commands
mysqlsh -- cluster.checkInstanceState()
SELECT * FROM performance_schema.replication_group_members;
Fix now
Restart group replication on all nodes with group_replication_bootstrap_group=ON on one node only.
Node expelled from group+
Immediate action
Identify the expelled node and rejoin it.
Commands
SELECT * FROM performance_schema.replication_group_members WHERE MEMBER_STATE='OFFLINE';
mysqlsh -- cluster.rejoinInstance('user@host:3306')
Fix now
Increase group_replication_member_expel_timeout to 30s.
Router reports no servers+
Immediate action
Check if cluster is ONLINE and Router is configured correctly.
Commands
mysqlsh -- cluster.status()
mysqlrouting --list-routes
Fix now
Restart MySQL Router service.
FeatureInnoDB ClusterTraditional Replication
FailoverAutomaticManual
ConsistencyStrong (Group Replication)Eventual (async)
Number of nodesMinimum 3Minimum 2
Client routingMySQL RouterManual or load balancer
Write scalabilitySingle primary (or multi-primary)Single primary
Setup complexityModerate (MySQL Shell)Low
⚙ Quick Reference
6 commands from this guide
FileCommand / CodePurpose
my.cnfserver_id=1Prerequisites and Environment Setup
create_cluster.jsmysqlsh --uri root@192.168.1.10:3306Creating the InnoDB Cluster
router_setup.shsudo apt-get install mysql-routerConfiguring MySQL Router
failover_test.shsudo systemctl stop mysqlTesting Failover and Recovery
monitoring.sqlSELECT * FROM performance_schema.replication_group_members;Monitoring and Maintenance
advanced_config.sqlSET GLOBAL group_replication_flow_control_mode = 'QUOTA';Scaling and Advanced Configuration

Key takeaways

1
InnoDB Cluster provides automatic failover and high availability using Group Replication.
2
Always use an odd number of nodes (minimum 3) to avoid split-brain.
3
MySQL Router simplifies client connections and handles failover transparently.
4
Tune group_replication parameters like member_expel_timeout for production stability.
5
Regularly monitor cluster health and test failover scenarios.

Common mistakes to avoid

4 patterns
×

Using an even number of nodes (e.g., 2).

×

Setting group_replication_member_expel_timeout too low (e.g., 5 seconds).

×

Not enabling GTID mode.

×

Using the same server_id on multiple nodes.

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Explain how InnoDB Cluster handles automatic failover.
Q02JUNIOR
What is the role of MySQL Router in InnoDB Cluster?
Q03SENIOR
How do you recover from a split-brain scenario in InnoDB Cluster?
Q01 of 03SENIOR

Explain how InnoDB Cluster handles automatic failover.

ANSWER
InnoDB Cluster uses Group Replication, which implements a consensus algorithm (Paxos-like) to elect a new primary when the current primary fails. The remaining nodes vote, and the one with the most up-to-date data becomes the new primary. MySQL Router detects the change and redirects client connections.
FAQ · 4 QUESTIONS

Frequently Asked Questions

01
What is the difference between InnoDB Cluster and traditional replication?
02
Can I use InnoDB Cluster with existing MySQL instances?
03
How many nodes do I need for production?
04
What happens if all nodes fail?
N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Notes here come from systems that actually shipped.

Follow
Verified
production tested
July 13, 2026
last updated
2,165
articles · all by Naren
🔥

That's MySQL & PostgreSQL. Mark it forged?

3 min read · try the examples if you haven't

Previous
SQL Server Management Studio (SSMS): Installation and Features
14 / 20 · MySQL & PostgreSQL
Next
PostgreSQL High Availability: Patroni, repmgr, and Failover