前言理论
MGR架构可以实现高可用,但实现failover,则需要安装InnoDB Cluster了。
MySQL shell和MySQL Router是InnoDB Cluster集群的一部分。
- MySQL shell用于安装和管理InnoDB Cluster集群,InnoDB Cluster集群通过新建的原数据库MySQL_innodb_cluster_metadata管理MGR集群状态,
- MySQL Router通过周期性的访问Cluster创建的MySQL_innodb_cluster_metadata库中的元数据获取集群成员信息,
再通过performance_schema的系统表获取可连接实例及其状态来实现failover和读负载均衡、读写分离的路由。 - MySQL Router非常轻量级,性能损耗小于1%,官方建议每台应用上部署一个mysqlrouter节点,优点是节省网络带宽。
缺点是mysqlrouter太轻量级了,只能提供简单的基于端口的读写路由(Port based routing)和基于权重轮询的负载均衡(Weighted Balance),
不支持基于SQL的读写分离(Query based routing)和空闲优先的负载均衡(Application Layer balancer)。
安装
基础配置
- /etc/hosts
[root@db1 mysqldata]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
192.168.123.101 db1
192.168.123.102 db2
192.168.123.103 db3
- 关闭selinux
vi /etc/selinux/config
SELINUX=disabled
- 关闭防火墙(生产环境建议不关闭,开放端口)
systemctl stop firewalld
systemctl disable firewalld
- 配置yum(避免依赖问题),自行百度
- 安装mysql yum源,
离线安装下载路径:https://dev.mysql.com/downloads/repo/yum/
5.7:wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
8.0 wget http://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
- 安装mysql mysqlshell mysqlroute
在对应的角色上安装对应的软件
yum install mysql-server
yum install mysql-shell
yum install mysql-route
- 修改my.cnf (根据实际用户需求更改)
server_id=1 ###每个节点必须不同
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW
transaction_write_set_extraction=XXHASH64
启动数据库修改密码
systemctl restart mysqld
修改root密码
mysql -uroot -p
alter user 'root'@'localhost' identified by 'Abc+1234';
use mysql
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'Abc+1234' WITH GRANT OPTION;
flush privileges;
mysql,mysqlshell都安装好了,
重启3个数据库实例,创建集群
mysqlsh
shell.connect ('root@db1:3306')
var cluster = dba.createCluster('MyCluster')
var cluster = dba.getCluster("MyCluster")
cluster.status()
# MyCluster是就集群的名字,自定义
添加节点
节点二、三上
reset master
节点一上:
cluster.addInstance('root@192.168.123.102:3306')
cluster.addInstance('root@192.168.123.103:3306')
cluster.status()
三个实例都要执
mysqlsh
mysql-js> shell.connect root@localhost:3306
mysql-js> dba.configureLocalInstance('root@localhost:3306')
mysql-js> shell.connect root@localhost:3306
mysql-js> dba.configureLocalInstance('root@localhost:3306')
mysql-js> shell.connect root@localhost:3306
mysql-js> dba.configureLocalInstance('root@localhost:3306')
官网原文:
The recommended deployment of MySQL Router is on the same host as the application. When using a sandbox deployment, everything is running on a single host, therefore you deploy MySQL Router to the same host. When using a production deployment, we recommend deploying one MySQL Router instance to each machine used to host one of your client applications. It is also possible to deploy MySQL Router to a common machine through which your application instances connect.
mysqlrouter配置
mysqlrouter --bootstrap root@db01:3306 --user=mysqlrouter
更具需求修改配置文件端口后
systemctl start mysqlrouter
或 nohup mysqlrouter --config /etc/mysqlrouter/mysqlrouter.conf &
==参考信息==
集群节点状态
- ONLINE: The instance is online and participating in the cluster.
- OFFLINE: The instance has lost connection to the other instances.
- RECOVERING: The instance is attempting to synchronize with the cluster by retrieving transactions it needs before it can become an ONLINE member.
- UNREACHABLE: The instance has lost communication with the cluster.
- ERROR: The instance has encountered an error during the recovery phase or while applying a transaction
mysqlsh命令帮助
查看集群状态
shell.connect ('root@innodb01:3306')
var cluster = dba.getCluster("MyCluster")
cluster.status()
获取getcluster命令的帮助
dba.help('getcluster')
获取集群的名字
dba.getCluster()
#### 常使用的几个重要命令 (mysqlsh的JS语法)
dba.checkInstanceConfiguration("root@hostname:3306") #检查节点配置实例,用于加入cluster之前
dba.rebootClusterFromCompleteOutage('myCluster'); #重启
dba.dropMetadataSchema(); #删除schema
var cluster = dba.getCluster('myCluster') #获取当前集群
cluster.checkInstanceState("root@hostname:3306") #检查cluster里节点状态
cluster.rejoinInstance("root@hostname:3306") #重新加入节点,我本地测试的时候发现rejoin一直无效,每次是delete后
addcluster.dissolve({force:true}) #删除集群
cluster.addInstance("root@hostname:3306") #增加节点
cluster.removeInstance("root@hostname:3306") #删除节点
cluster.removeInstance('root@host:3306',{force:true}) #强制删除节点
cluster.dissolve({force:true}) #解散集群
cluster.describe(); #集群描述
注意事项:
- 请保证集群中的数据库表都存在主键,不然会挂掉;
- 组复制有以下限制:
- 事物锁缺失问题:
- 组复制建议,事物隔离级别,read commit
- 序列化隔离级别:多主模式不支持
- 并发DDL和DML: 多主模式下,不支持 一边对一个表进行DDL,另一边进行更新,这样对于DDL在其他实例上操作有未检出的风险
- 外键级联约束:多主模式下,多级外键依赖对引起多级操作, 因此可能导致未知冲突,建议打开 group_replication_enforce_update_everywhere_checks=ON
- 大事物,超过5秒未提交,会导致组通信失败,
- 多主模式下:select * for update 会导致 死锁。因为这个锁并非全组共享。
- 部分复制不支持:组复制下,设置部分复制,会过滤事物,导致组事物不一致。
- Mysql 8.0.11 group_replication_enforce_update_everywhere_checks=ON 多主模式下不支持。
- 停止复制的情况下,某个节点执行命令后再启动,会因为本地有私有事物,无法加入集群。需要全局 reset master 重新开始集群复制。
1. 如何重置Innodb cluster集群环境
主节点:
mysql-js>dba.dropMetadataSchema(); 登录mysql-shell清空集群
mysql> stop group_replication;
mysql> reset master; (清空日志,确保和从库的表没有冲突奥,)
mysql> reset slave;
其他节点(主要清理和主库的主从信息, 确保主库和从库的表没有冲突奥)
mysql> stop group_replication;
mysql> reset master;
mysql> reset slave
2. 如何将Multi-Primary改为Single-Primary?
a) 解散原来的集群:mysql-js> cluster.dissolve({force: true})
b) 每台主机MySQL修改如下配置:
mysql> set global group_replication_enforce_update_everywhere_checks=OFF;
mysql> set global group_replication_single_primary_mode=ON;
c) 重新创建集群:
mysql-js> var cluster = dba.createCluster('mysqlCluster');
mysql-js> cluster.addInstance('chianyu@svr2:3306');
mysql-js> cluster.addInstance('chianyu@svr3:3306');