不知道mysql5.7从什么时候加入了innodb cluster,于是mysql就有了2种集群路线,一个是使用NDB的mysql cluster,一个是用innodb 的mysql innodb cluster。
MySQL Cluster
NDB意思是Network DataBase,是mysql cluster(非mysql)专用引擎,离开集群无法工作。NDB是一个shared nothing的内存数据库,不过官网说他会存储部分数据在硬盘上(猜测是blob类型,可能还有text类型)。NDB数据与mysqld进程分离,存储在专门的数据节点中,名为ndbd或ndbmtd(ndbd的多线程版本)的进程。NDB集群还自带数据分片功能,他通过数据交叉冗余提供高可用性。
详见NDB集群概述、NDB集群核心概念、NDB集群节点、副本、分区。
NDB大致使用限制如下
1、NDB的创建索引的字段最大3072byte 2、NDB不能在text上建索引 3、NDB唯一索引字段不能为空 4、NDB最大索引条数配置项 MaxNoOfOrderedIndexes,每表最大16个 5、NDB最大数据节点为48个,整个集群(管理节点、sql节点、配置节点)最大255个 6、NDB只支持READ COMMITTED事务级别(一般够用了) 7、NDB集群锁表操作(alter table)存在不能全锁的问题
详见NDB使用限制。
mysql官网还提供了一个innodb与ndb集群的性能对比表格。大致在集群同步和故障恢复有些差异,大致如下:
Feature | InnoDB (MySQL 5.7) | NDB 7.5/7.6 |
Storage Limits | 64TB | 128TB (as of NDB 7.5.2) |
Transactions | All standard types | READ COMMITTED |
MVCC | Yes | No |
Data Compression | Yes | No (NDB checkpoint and backup files can be compressed) |
Large Row Support (> 14K) | Supported for VARBINARY, VARCHAR, BLOB, and TEXT columns | Supported for BLOB and TEXT columns only (Using these types to store very large amounts of data can lower NDB performance) |
Replication Support | Asynchronous and semisynchronous replication using MySQL Replication; MySQL Group Replication | Automatic synchronous replication within an NDB Cluster; asynchronous replication between NDB Clusters, using MySQL Replication
(Semisynchronous replication is not supported) |
Time for Node Failure Recovery | 30 seconds or longer | Typically < 1 second |
Real-Time Performance | No | Yes |
In-Memory Tables | No | Yes (Some data can optionally be stored on disk; both in-memory and disk data storage are durable) |
Concurrent and Parallel Writes | Yes | Up to 48 writers, optimized for concurrent writes |
Hash Indexes | No | Yes |
MySQL InnoDB Cluster
innodb集群则更普通一些,mysql5.7自带了group repliction插件,再配合mysql-shell(集群控制)、mysql-router(高可用代理,故障恢复)一起提供集群功能。
在windows上安装可以直接在装server的时候选择sandbox(似乎5.7.21的安装包开始提供sandbox功能)安装配置好的测试样本体验mysql集群。sandbox的安装路径为
C:\Users\Administrator\MySQL\mysql-sandboxes
若需要在单机上进行多实例模拟集群,则可以这样安装服务。
1、按配置同步副本组增加my.ini中配置
# Replication Framework 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 # Group Replication Settings transaction_write_set_extraction=XXHASH64 loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" loose-group_replication_start_on_boot=off loose-group_replication_local_address= "127.0.0.1:24901" loose-group_replication_group_seeds= "127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903" loose-group_replication_bootstrap_group=off
2、创建数据库、安装服务
mysqld --initialize-insecure --basedir="c:\Program Files\MySQL\MySQL Server 5.7" --datadir="d:\ProgramData\MySQL\MyS QL Server 5.7\data\1" mysqld --initialize-insecure --basedir="c:\Program Files\MySQL\MySQL Server 5.7" --datadir="d:\ProgramData\MySQL\MyS QL Server 5.7\data\2" mysqld --initialize-insecure --basedir="c:\Program Files\MySQL\MySQL Server 5.7" --datadir="d:\ProgramData\MySQL\MyS QL Server 5.7\data\3" mysqld --install MySQL57_1 --defaults-file="d:\ProgramData\MySQL\MySQL Server 5.7\config\my_1.ini" mysqld --install MySQL57_2 --defaults-file="d:\ProgramData\MySQL\MySQL Server 5.7\config\my_2.ini" mysqld --install MySQL57_3 --defaults-file="d:\ProgramData\MySQL\MySQL Server 5.7\config\my_3.ini"
-- 创建同步用户 SET SQL_LOG_BIN=0; --关闭同步(创建用户操作可能会导致同步出错) CREATE USER rpl_user@'%' IDENTIFIED BY 'password'; GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; FLUSH PRIVILEGES; SET SQL_LOG_BIN=1; CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery'; -- 安装插件 INSTALL PLUGIN group_replication SONAME 'group_replication.dll'; -- 在主库上执行 SET GLOBAL group_replication_bootstrap_group=ON; --在副本同步开始前创建新的副本组 START GROUP_REPLICATION; SET GLOBAL group_replication_bootstrap_group=OFF; -- 在从库上执行 START GROUP_REPLICATION;
4、使用mysql shell 建立、配置集群
--给集群管理账户(root)加集群元信息表权限 GRANT ALL PRIVILEGES ON mysql_innodb_cluster_metadata.* TO cluster_admin@'%' WITH GRANT OPTION; GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO cluster_admin@'%' WITH GRANT OPTION; GRANT SELECT ON *.* TO cluster_admin@'%' WITH GRANT OPTION;
//mysql shell 下配置集群(会提示localhost/172.0.0.1只能用于sandbox测试集群,可以配到其他ip上) //连接主库 shell.connect('root@172.31.35.109:3316') //查看是否可以建立集群,根据提示更改配置 dba.configureLocalInstance('root@172.31.35.109:3316') //创建集群 var cluster = dba.createCluster('TestCluster') //添加从库 cluster.addInstance('root@172.31.35.109:3317') //获取集群实例 var cluster = dba.getCluster() var cluster = dba.getCluster('TestCluster') //查看集群状态 cluster.status() //mysql shell具体参考帮助在mysql官网文档上并不清楚 //可以参考github上源代码 https://github.com/mysql/mysql-shell/tree/1.0
5、配置mysql router
windows上直接在mysql installer里点击 Reconfiguration进行配置就可以了,会生成一个windows服务。
6、修改配置
将配置文件中group_replication_start_on_boot=off 改为group_replication_start_on_boot=on 这样就能在数据库重启后自动加入同步组(集群)
mysql innodb cluster大致限制如下
1、表锁、命名锁等特殊锁无法使用 2、基本只支持READ COMMITTED事务级别 3、并发ddl和dml的冲突 4、外键冲突 5、大型事务可能导致同步失败(超时) 6、多主模式下可能产生脑裂问题。一台主服务在失败恢复后可能竞争主服务地位,可能造成所有写入等待。
其实很多跟ndb集群差不多。脑裂问题可能比较麻烦,可能mysql官方没用raft等选举算法解决主库选举问题。
一些问题的解决方案
1、mysql部分同步失败
可能存在部分语句无法同步或者无法执行(比如说创建用户),导致集群数据库状态为error或者missing。
如果是部分sql无法同步,比如说从库数据比主库更新,可以参考这个
--现象可见于mysql错误日志 --2018-01-19T06:54:43.700510Z 0 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: f072afc8-6b82-4c16-aed8-d44c94758dea:1-6:1000003-1000006 > Group transactions: 03b5beed-fc36-11e7-a9b9-00ffa83c6c25:1-21, --2d25a444-fce0-11e7-b9ed-00ffa83c6c25:1-15, --f072afc8-6b82-4c16-aed8-d44c94758dea:1-7' --各库查看同步过的事务 SELECT @@global.gtid_executed; --找到没同步过的事务在没同步的库里执行 SET GTID_NEXT='f072afc8-6b82-4c16-aed8-d44c94758dea:1'; BEGIN; COMMIT; --... SET GTID_NEXT='f072afc8-6b82-4c16-aed8-d44c94758dea:7'; --重置游标? SET GTID_NEXT='AUTOMATIC'; --各库重启同步 START GROUP_REPLICATION;
如果是sql无法执行。还有第二种方案
--在同步失败的数据库里重置 RESET MASTER; -启动同步 START GROUP_REPLICATION;
第三种方案方案
//mysql shell 重新检查 var cluster = dba.getCluster() cluster.rescan() //按提示修复/忽略sql
2、集群恢复
dba.rebootClusterFromCompleteOutage()
3、脑裂问题
cluster.forceQuorumUsingPartitionOf('root@172.31.35.109:3316')
其余参考