Ubuntu20.04搭建MySQL InnoDB 集群

简介

MySQL InnoDB Cluster(集群)为 MySQL 提供了完整的高可用性解决方案。通过使用 MySQL Shell中包含的 AdminAPI,可以轻松配置和管理一组至少三个 MySQL 服务器实例,以充当 InnoDB Cluster。

InnoDB Cluster 中的每个 MySQL 服务器实例都运行 MySQL Group Replication(组复制),它提供了在 InnoDB Cluster 内复制数据的机制,并具有内置的故障转移功能。

InnoDB Cluster概览

InnoDB Cluster建立在组复制之上,提供了自动成员管理、容错、自动故障转移等功能。InnoDB Cluster 通常以单主模式运行,具有一个主节点(读写)和多个从节点(只读)。还可以利用多主模式让其中所有节点都是主节点。甚至可以在线更改在 InnoDB Cluster 的拓扑,以确保尽可能高的可用性。

要开始使用 InnoDB Cluster,需要下载并安装MySQL Shell,同时还需要一些安装了 MySQL Server 实例的服务器。

前置工作

服务器信息

内网IP HostName映射
172.27.8.1 mysql-node-01
172.27.8.2 mysql-node-02
172.27.8.3 mysql-node-03
172.27.8.4 mysql-node-04

配置IP与HostName映射的绑定关系

1> 按照上面服务器信息,修改IP地址对应的HostName,登录每一个服务器,修改为对应的映射

vi /etc/hostname

2> 在每一台服务器的hosts文件夹中添加IP与HostName映射的绑定关系

vi /etc/hosts

内容如下:

172.27.8.1      mysql-node-01   mysql-node-01
172.27.8.2      mysql-node-02   mysql-node-02
172.27.8.3      mysql-node-03   mysql-node-03
172.27.8.4      mysql-node-04   mysql-node-04

安装MySQL8.0

为每一台服务器安装MySQL8.0并设置相同的root密码,在my.cnf中设置server-id,确保每台服务器的server-id不重复。
具体安装步骤可以查看《Ubutun20.04编译安装MySQL8.0.28

InnoDB 集群要求

由于是InnoDB 集群,故数据库中的所有表都需要使用InnoDB 存储引擎。
可以通过设置系统变量disabled_storage_engines来防止使用其他存储引擎,例如:

disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"

更多要求可以查看官方文档:《组复制要求》、《InnoDB 集群要求

Innodb 集群的限制

InnoDB Cluster建立在组复制之上,组复制节点的 MySQL 服务器的最大数量是 9。也就意味着Innodb 集群最多可以容纳9台 MySQL 实例。
更多限制可以查看官方文档

安装MySQL Shell 8.0

只需要在 mysql-node-01 上安装即可。

MySQL Shell简介

MySQL Shell 是 MySQL 的客户端命令行工具。通过在该工具中执行命令可以简便的配置 InnoDB 集群,使配置工作不在那么繁琐。

添加APT存储库

首先,将 MySQL APT 存储库添加到系统的软件存储库列表中。
下载发行包:https://dev.mysql.com/downloads/repo/apt/

cd /home
wget https://repo.mysql.com//mysql-apt-config_0.8.23-1_all.deb

使用以下命令安装下载的发行包:

dpkg -i /home/mysql-apt-config_0.8.23-1_all.deb

更新包信息

apt-get update

安装

apt-get install mysql-shell

检验安装结果

mysqlsh --version

正确输出版本号则代表安装成功。

配置实例

mysqlsh
mysql-js> dba.configureInstance('root@localhost:3306')

连接后弹出提示需要开启GTID,输入y开启即可:

检查实例配置是否适合InnoDB Cluster

mysql-js> dba.checkInstanceConfiguration('root@localhost:3306')

创建 InnoDB 集群

登录MySQL实例

方法一:

mysqlsh --uri=mysql://root@localhost:3306


更多关于--uri的用法可参考官方文档

方法二:

mysqlsh
MySQL JS > \connect root@localhost:3306
或
MySQL JS > shell.connect('root@localhost:3306')

创建 InnoDB 集群

mysql-js> var cluster = dba.createCluster('testCluster')

要检查集群是否已创建

mysql-js> cluster.status()

添加实例至 InnoDB 集群

InnoDB Cluster 中至少需要三个实例,以使其能够容忍一个实例的故障。添加更多实例会增加对 InnoDB Cluster 故障的容忍度。

修改server-id

确保要添加的实例的server-id与之前的不同。

配置实例

mysqlsh
MySQL  JS > dba.configureInstance('root@172.27.8.2:3306')

连接后弹出提示需要开启GTID,输入y开启即可:

检查实例状态

cluster.checkInstanceState()用于验证实例上的现有数据不会阻止其加入集群。

mysqlsh --uri=mysql://root@localhost:3306
mysql-js> var cluster=dba.getCluster()
mysql-js> cluster.checkInstanceState('root@172.27.8.2:3306')


可以将状态为 OK 的实例添加到集群中,因为该实例上的任何数据都与集群一致。换句话说,被检查的实例没有执行任何与集群执行的 GTID 冲突的事务,并且可以恢复到与其他集群实例相同的状态。
更多状态解释可以参考官方文档

添加实例至 InnoDB 集群

mysql-js> cluster.addInstance('root@172.27.8.2:3306')

添加成功的正确提示:

如果出现如下错误信息:

则需要先在该节点服务器添加IP与HostName映射的绑定关系。

通过以上方法,将mysql-node-02mysql-node-03都加入集群,留一个mysql-node-04先不加入。

集群测试

此时通过cluster.status()指令可以查看集群状态,其中memberRolePRIMARY的为主节点,只有该节点可以写入,其余节点只能读,无法写入。
可以连接主节点进行增伤改查测试,可以发现从节点也会同步执行。

集群加入新节点测试

mysql-node-01是主节点,可以在该节点导入一些数据用作测试,模拟当前集群(3个节点)已运行一段时间。现在需要加入一个全新的节点mysql-node-04,新节点是新安装的mysql实例,里面没有任何业务数据。
经测试,加入mysql-node-04节点后,该节点会自动从之前的集群中克隆数据并开启同步,不需要再手动导入备份的数据。

mysql shell 常用命令

操作 方法示例
连接实例 \connect root@localhost:3306
检测实例状态 dba.checkInstanceConfiguration('root@172.27.8.2:3306')
退出 \quit
自动修正实例设置 dba.configureInstance('root@172.27.8.2:3306')
删除集群元数据 dba.dropMetadataSchema()
创建集群 var cluster = dba.createCluster('clusterTest')
获取集群 var cluster = dba.getCluster()
向集群中添加实例 cluster.addInstance('root@172.27.8.2:3306')
从集群中删除实例 cluster.removeInstance('root@172.27.8.2:3306')
从集群中删除实例(强制) cluster.removeInstance('root@172.27.8.2:3306',{force:true})
查看集群状态 cluster.status()
查看集群描述 cluster.describe()
重启集群 var cluster = dba.rebootClusterFromCompleteOutage()
解散集群 cluster.dissolve({force:true})
指定一个新的主节点 cluster.setPrimaryInstance('root@172.27.8.2:3306')
切换到多主模式 cluster.switchToMultiPrimaryMode()
切换到单主模式 cluster.switchToSinglePrimaryMode('root@172.27.8.2:3306')
更改集群设置 cluster.setOption('clusterName','newCluster')
更改集群实例设置 cluster.setInstanceOption('root@172.27.8.2:3306', 'exitStateAction', 'READ_ONLY')

常见问题

metadata exists, instance belongs to that metadata, but GR is not active

执行命令var cluster = dba.getCluster()时报:

Dba.getCluster: This function is not available through a session to a standalone instance (metadata exists, instance belongs to that metadata, but GR is not active) (MYSQLSH 51314)

此时可尝试重启集群:

dba.rebootClusterFromCompleteOutage()

若依然不能解决,则登录MySQL,然后启动该节点的group replication:

set global group_replication_bootstrap_group=on;
start group_replication;
set global group_replication_bootstrap_group=off;

卡在Cancelling active GR auto-initialization at xxx 一直不动

当所有mysql节点都重启后,使用dba.rebootClusterFromCompleteOutage()重启集群时,会卡在Cancelling active GR auto-initialization at xxx
可以通过在所有节点执行pkill -9 mysqld来模拟这种情况。然后在所有节点启动mysql服务。在其中某个节点执行dba.rebootClusterFromCompleteOutage()时,会一直卡在Cancelling active GR auto-initialization at xxx

此时可以尝试重启服务器后,重新执行dba.rebootClusterFromCompleteOutage()命令,也许可以成功重启集群。如果实现不行,就说明群集元数据已严重损坏,则可能需要删除元数据并从头开始重新创建群集。可以先在各服务器使用dba.dropMetadataSchema()删除集群元数据,然后重新创建集群。

发表评论

邮箱地址不会被公开。 必填项已用*标注