Let’s begin by starting the shell and deploying three servers using the AdminAPI. In this case, we will use the deploySandboxInstance() method in the dba object to create new instances for each server. All of these will run on our localhost. Listing 1- 5 demonstrates how to deploy three servers. I highlight the commands used to help identify the commands from the messages.
Listing 1-5. Creating Local Server Instances
$ mysqlsh
MySQL Shell 8.0.11
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type '\help' or '\?' for help; '\quit' to exit.
MySQL JS > dba.deploySandboxInstance(3307)
A new MySQL sandbox instance will be created on this host in /Users/cbell/mysql-sandboxes/3307
ChApTer 1 InTroduCIng MySQL 8—A new BegInnIng
Please enter a MySQL root password for the new instance:
Deploying new MySQL instance...
Instance localhost:3307 successfully deployed and started.
Use shell.connect('root@localhost:3307'); to connect to the instance.
MySQL JS > dba.deploySandboxInstance(3308)
A new MySQL sandbox instance will be created on this host in /Users/cbell/mysql-sandboxes/3308
Please enter a MySQL root password for the new instance:
Deploying new MySQL instance...
Instance localhost:3308 successfully deployed and started.
Use shell.connect('root@localhost:3308'); to connect to the instance.
MySQL JS > dba.deploySandboxInstance(3309)
A new MySQL sandbox instance will be created on this host in /Users/cbell/mysql-sandboxes/3309
Please enter a MySQL root password for the new instance:
Deploying new MySQL instance...
Instance localhost:3309 successfully deployed and started.
Use shell.connect('root@localhost:3309'); to connect to the instance.
MySQL JS >
Note that the text explains that we are using a sandbox, which is a term applied to running servers on the localhost in a special directory: the mysql-sandboxes folder in the user home. In particular in this case, we use /Users/cbell/mysql-sandboxes. Note that we now have three servers running on ports 3307, 3308, and 3309. Note also that the shell will prompt you for the new password.
Tip JavaScript is case sensitive so make sure you use the correct spelling for
variables, objects, and methods. That is, a variable named abc is not the same
variable named Abc.
28
The next thing we need to do is setup a new cluster. We do this with the
createCluster() method in the dba object. But first, we must connect to the server we want to make our primary server. Listing 1-6 demonstrates how to create the cluster.
Note that this is a continuation of our shell session and demonstrates how to create a new cluster.
Listing 1-6. Creating a Cluster in InnoDB Cluster MySQL JS > \connect root@localhost:3307 Creating a session to 'root@localhost:3307' Enter password:
Your MySQL connection id is 12
Server version: 8.0.11 MySQL Community Server (GPL)
No default schema selected; type \use <schema> to set one.
MySQL localhost:3307 ssl JS > my_cluster = dba.createCluster('my_cluster') A new InnoDB cluster will be created on instance 'root@localhost:3307'.
Creating InnoDB cluster 'my_cluster' on 'root@localhost:3307'...
Adding Seed Instance...
Cluster successfully created. Use Cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to one server failure.
<Cluster:my_cluster>
Note that we named the cluster my_cluster and used a variable of the same name to store the object returned from the createCluster() method. Note that the first server we connected has become the primary (master).
Next, we add the other two server instances to complete the cluster using the addInstance() of our new my_cluster object. These servers automatically become secondary servers (slaves) in the group. Listing 1-7 shows how to add the instances to the cluster.
ChApTer 1 InTroduCIng MySQL 8—A new BegInnIng
Listing 1-7. Adding Instances to the Cluster
MySQL localhost:3307 ssl JS > my_cluster = dba.getCluster('my_cluster')
<Cluster:my_cluster>
MySQL localhost:3307 ssl JS > my_cluster.addInstance('root@
localhost:3308')
A new instance will be added to the InnoDB cluster. Depending on the amount of data on the cluster this might take from a few seconds to several hours.
Please provide the password for 'root@localhost:3308':
Adding instance to the cluster ...
The instance 'root@localhost:3308' was successfully added to the cluster.
MySQL localhost:3307 ssl JS > my_cluster.addInstance('root@
localhost:3309')
A new instance will be added to the InnoDB cluster. Depending on the amount of data on the cluster this might take from a few seconds to several hours.
Please provide the password for 'root@localhost:3309':
Adding instance to the cluster ...
The instance 'root@localhost:3309' was successfully added to the cluster.
Once the cluster is created and the instances are added, we can get the status of the cluster using the status() method of our my_cluster object as shown in Listing 1-8.
Listing 1-8. Getting the Status of the Cluster
MySQL localhost:3307 ssl JS > my_cluster.status() {
"clusterName": "my_cluster", "defaultReplicaSet": { "name": "default",
"primary": "localhost:3307", "ssl": "REQUIRED",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
30
"topology": {
"localhost:3307": {
"address": "localhost:3307", "mode": "R/W",
"readReplicas": {}, "role": "HA", "status": "ONLINE"
},
"localhost:3308": {
"address": "localhost:3308", "mode": "R/O",
"readReplicas": {}, "role": "HA", "status": "ONLINE"
},
"localhost:3309": {
"address": "localhost:3309", "mode": "R/O",
"readReplicas": {}, "role": "HA", "status": "ONLINE"
} } } }
MySQL localhost:3307 ssl JS > \exit Bye!
At this point, we’ve seen how InnoDB Cluster can setup servers and add them to the group. What you do not see behind the scenes is all of the Group Replication mechanisms—you get them for free! How cool is that?
Now that we have a cluster, there is one more thing we need to do to enable applications to use the fault tolerance features of Group Replication. That is, we need to be able to connect to the cluster and interact with MySQL even if one of the servers fails. Note that because we only have three servers, we can only tolerate one failure. For example, solving for f in the number of faults tolerated by Group Replication, we get 3 = 2f + 1 or f = 1.
ChApTer 1 InTroduCIng MySQL 8—A new BegInnIng
We must now use MySQL Router to manage the connections for our application.
Although we don’t have an application to demonstrate, we can see this in action using the shell. Now let’s see how easy it is to set up the router. Listing 1-9 shows how to start the router in bootstrap mode. Note that by connecting to the cluster, the router automatically gets the members of the group. Recall from the previous section, this is one of the tenets of Group Replication via the membership service.
Listing 1-9. Setting Up the MySQL Router
& mysqlrouter --bootstrap localhost:3307 --user=cbell Please enter MySQL password for root:
Bootstrapping system MySQL Router instance...
MySQL Router has now been configured for the InnoDB cluster 'my_cluster'.
The following connection information can be used to connect to the cluster.
Classic MySQL protocol connections to cluster 'my_cluster':
- Read/Write Connections: localhost:6446 - Read/Only Connections: localhost:6447
X protocol connections to cluster 'my_cluster':
- Read/Write Connections: localhost:64460 - Read/Only Connections: localhost:64470
& mysqlrouter &
Okay, now we have the router running. Our applications can use the features of the router to automatically reroute our application connections should something happen to one of the servers in the cluster.
Let’s see a short demonstration of this feature. In this case, we will use the shell to connect to the cluster via the router on port 6446 as shown in Listing 1-9. We use this port because the router is used to forward connections automatically. That is, if the server we’re connected to goes down—for instance the one on port 3307—we do not have to restart our application to reconnect to a server on another port. Thus, the router, routes the communications for us. Let’s see this in action.
Listing 1-10 demonstrates connecting to the cluster via the router. We switch to SQL mode in the shell and use an SQL command to see the port of the server where we’re connected. We then switch back to JavaScript and use the AdminAPI to kill the instance.
We then attempt to issue the SQL command again and now notice that, once the shell has automatically reconnected, we are now connected to another server. Cool!
32
Listing 1-10. Fault Tolerance Demonstration
$ mysqlsh --uri root@localhost:6446 --sql Creating a session to 'root@localhost:6446' Enter password:
Your MySQL connection id is 47
Server version: 8.0.11 MySQL Community Server (GPL)
No default schema selected; type \use <schema> to set one.
MySQL Shell 8.0.11
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type '\help' or '\?' for help; '\quit' to exit.
MySQL localhost:6446 ssl SQL > SELECT @@port;
+---+
| @@port | +---+
| 3307 | +---+
1 row in set (0.00 sec)
MySQL localhost:6446 ssl SQL > \js Switching to JavaScript mode...
MySQL localhost:6446 ssl JS > dba.killSandboxInstance(3307) The MySQL sandbox instance on this host in
/Users/cbell/mysql-sandboxes/3307 will be killed Killing MySQL instance...
Instance localhost:3307 successfully killed.
MySQL localhost:6446 ssl JS > \sql
Switching to SQL mode... Commands end with ; MySQL localhost:6446 ssl SQL > SELECT @@port;
ChApTer 1 InTroduCIng MySQL 8—A new BegInnIng
ERROR: 2006 (HY000): MySQL server has gone away The global session got disconnected.
Attempting to reconnect to 'root@localhost:6446'..
The global session was successfully reconnected.
MySQL localhost:6446 ssl SQL > SELECT @@port;
+---+
| @@port | +---+
| 3308 | +---+
1 row in set (0.00 sec)
MySQL localhost:6446 ssl SQL > \quit Bye!
Note that although the shell had lost the connection it automatically reconnected so that we can retry the command. Very nice.
Finally, let’s discover how to put the instance that failed back into service. In this case, we simulate recovering a downed server adding it back to the cluster where Group Replication ensures that the new server becomes consistent by applying any missing transactions. Listing 1-11 shows the commands you can use to recover the server.
Listing 1-11. Recovering a Lost Server
$ mysqlsh --uri root@localhost:6446
MySQL localhost:6446 ssl JS > dba.startSandboxInstance(3307) The MySQL sandbox instance on this host in
/Users/cbell/mysql-sandboxes/3307 will be started Starting MySQL instance...
Instance localhost:3307 successfully started.
MySQL localhost:6446 ssl JS > my_cluster = dba.getCluster('my_cluster')
<Cluster:my_cluster>
MySQL localhost:6446 ssl JS > my_cluster.rejoinInstance('root
@localhost:3307')
Rejoining the instance to the InnoDB cluster. Depending on the original problem that made the instance unavailable, the rejoin operation might not be
34
successful and further manual steps will be needed to fix the underlying problem.
Please monitor the output of the rejoin operation and take necessary action if the instance cannot rejoin.
Please provide the password for 'root@localhost:3307':
Rejoining instance to the cluster ...
The instance 'root@localhost:3307' was successfully rejoined on the cluster.
The instance 'localhost:3307' was successfully added to the MySQL Cluster.
MySQL localhost:6446 ssl JS > \q Bye!
It is clear that using the shell to setup and manage a cluster is a lot easier than setting up and managing a standard Group Replication setup. In particular, you don’t have to manually configure replication! Better still, should a server fail, you don’t have to worry about reconfiguring your application or the topology to ensure the solution remains viable—InnoDB Cluster does this automatically for you.
To learn more about InnoDB Cluster, see the online documentation at https://dev.mysql.com/doc/mysql-innodb-cluster/en/.