灯下哥谭 灯下哥谭
首页
关于
  • Hermes Agent 平台
  • Claude Code
  • OpenClaw
  • GPU 推理节点运维
  • DeepSeek Harness
  • MySQL 运维知识地图
  • Elasticsearch 运维知识地图
  • Redis 运维知识地图
  • TiDB 体系
  • DBA 常用 SQL 与命令
  • Nginx 运维知识地图
  • Prometheus 监控
  • Docker
  • Systemd
  • Iptables
  • Firewalld
  • Sshd
  • MySQL8 运维 SOP 手册
  • MySQL 实战 45 讲(读书笔记)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

灯下哥谭

灯还亮着
首页
关于
  • Hermes Agent 平台
  • Claude Code
  • OpenClaw
  • GPU 推理节点运维
  • DeepSeek Harness
  • MySQL 运维知识地图
  • Elasticsearch 运维知识地图
  • Redis 运维知识地图
  • TiDB 体系
  • DBA 常用 SQL 与命令
  • Nginx 运维知识地图
  • Prometheus 监控
  • Docker
  • Systemd
  • Iptables
  • Firewalld
  • Sshd
  • MySQL8 运维 SOP 手册
  • MySQL 实战 45 讲(读书笔记)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • MySQL

    • MySQL 运维知识地图:从入门配置到高可用排障
    • MySQL8 配置文件 my.cnf 重要参数解读
    • MySQL 导出 CSV 中文乱码:字符集链路从头讲一遍
    • MySQL 角色管理
    • MySQL网络抓包审计
    • MySQL 性能压测:Sysbench 1.0 实战
    • MySQL Router 实现读写分离
    • Gh-ost重建表,清除表碎片率
    • MySQL MGR配合MySQL-router实现innodb-cluster
    • MySQL 快速分析binlog定位问题
    • MySQL执行计划分析
    • DBA常用SQL和命令整理备查
    • 单表数据同步方案选型:为什么不该用 mysqldump 做「实时同步」
    • MySQL的事务隔离级别
    • MySQL存储过程批量生成数据
    • MySQL insert on duplicate key update,replace into , insert ignore的理解
    • MySQL不同字符集之间的区别和选择
    • MySQL为什么有时候会选错索引
    • MySQL死锁问题
    • MySQL使用SQL语句查重去重
    • MySQLdump逻辑备份
    • MySQL 基于 GTID 主从复制:跳过异常事务的正确姿势
    • MySQL8快速克隆插件使用指南
    • MySQL8双1设置保障安全
    • MySQL锁
    • innodb cluster安装
      • 1. 部署环境及初始化
      • 安装mysql
      • 利用MySQL Shell构建MGR集群
      • 部署MySQL Router,实现读写分离以及故障自动转移
        • 参数解释
      • 验证:集群是不是真的可用
      • 坑与边界
    • OPTIMIZE TABLE 和 ANALYZE TABLE 的区别:用实测数据说话
    • MySQLReplicaSet 安装
    • MySQL 的 Left join、Right join 和 Inner join 的区别
    • ORDER BY 配合 LIMIT 触发的索引选择陷阱
  • Redis

  • 高性能KV

  • TiDB

  • Elasticsearch

  • 数据管道

  • 其他数据库

  • 数据库
  • MySQL
灯下哥谭
2022-08-13
目录

innodb cluster安装

# 1. 部署环境及初始化

为了简单起见,建议用yum方式标准化安装MySQL Shell、Router

  1. MySQL官方的yum源,需要先下载安装repo包,下载地址:
# EL7;EL8/EL9 请把 el7 换成对应版本,版本号也会随官方更新,先到 dev.mysql.com/downloads/repo/yum/ 确认当前的 repo 包名
yum -y install https://dev.mysql.com/get/mysql80-community-release-el7-4.noarch.rpm
1
2
  1. 用yum安装MySQL相关的软件包了
yum install -y mysql-shell mysql-router
#也可以用rpm包安装
 wget https://downloads.mysql.com/archives/get/p/43/file/mysql-shell-8.0.26-1.el7.x86_64.rpm  
 wget https://downloads.mysql.com/archives/get/p/41/file/mysql-router-community-8.0.26-1.el7.x86_64.rpm

1
2
3
4
5
  1. 网络调整
# 放行集群内部互访(MySQL 端口 + Group Replication 通信端口)
for ip in 192.0.2.11 192.0.2.12 192.0.2.13; do
  sudo iptables -I INPUT -s ${ip}/32 -p tcp -m multiport --dports 3366,33660 -j ACCEPT
done
sudo service iptables save
1
2
3
4
5

为什么要单独放行 33660:Group Replication 走的是独立于 MySQL 端口的组通信端口(group_replication_local_address 指定,惯例是 MySQL 端口后加 0 或另取一段),只放行 3366 会导致节点能连上、但加入组时卡在 RECOVERING 一直不进 ONLINE——这是新搭集群最常见的一个卡点。

版本说明

本文写于 2022-08,基于 MySQL 8.0 InnoDB Cluster(Group Replication + MySQL Router + MySQL Shell)。
核心组件与部署流程在 8.0 后续小版本上未有破坏性变更,经 2026-07 复核仍适用;MySQL Shell 的具体命令语法在新版本上有少量增补(如更完善的 dba.configureInstance() 校验项),部署时建议核对当前 MySQL Shell 版本的官方文档。

  1. CPU磁盘内存调整
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.d/rc.local

cat /sys/block/sdb/queue/scheduler
echo noop >/sys/block/sdb/queue/scheduler

cpupower frequency-info --governors

cpupower frequency-set --governor performance

cpupower frequency-info --policy
1
2
3
4
5
6
7
8
9
10
11
  1. 如果用的是 GreatSQL 分支,它依赖 jemalloc,需要先装上(官方 MySQL 不需要这一步,可跳过)
yum -y install jemalloc jemalloc-devel

#检查
[root@db-01]# ldconfig
[root@db-01]# ldconfig -p | grep libjemalloc
1
2
3
4
5
  1. /etc/hosts绑定IP和主机名防止创建mgr时报错 192.0.2.11 mytest-dbtest01 192.0.2.12 mytest-dbtest02 192.0.2.13 mytest-dbtest03

# 安装mysql

  1. 安装 mysql(这里用的是内部封装的安装脚本,换成你自己的安装方式即可;缓冲池按机器实际内存给,参数取舍见 MySQL8 配置文件 my.cnf 重要参数解读)
python install_mysql8.py install --instance-ports=3366 --innodb-buffer-pool-size=<物理内存的 50%~70%>
1
  1. 修改root密码
SET SQL_LOG_BIN=0;

alter user 'root'@'localhost' identified by '';

rename user 'root'@'localhost' to 'admin'@'localhost';

SET SQL_LOG_BIN=1;
1
2
3
4
5
6
7
  1. 避免使用root请创建mgr_admin用户
create user `dba_mgr_admin`@`192.0.2.%` identified by '';

GRANT ALL PRIVILEGES ON *.* TO `dba_mgr_admin`@`192.0.2.%` WITH GRANT OPTION;
-- 注:AdminAPI 的建集群操作确实需要很高的权限,官方也是这么建议的。
-- 但这个账号只应对集群内网段开放(上面的 192.0.2.%),且不要复用为业务账号。
-- 集群建好后日常运维可以降级到 MySQL Shell 文档列出的最小权限集。
1
2
3
4
5
6

# 利用MySQL Shell构建MGR集群

  1. 登录第一台mysql
mysqlsh --uri dba_mgr_admin@192.0.2.11:3366
1
  1. 检查配置
dba.configureInstance();
dba.checkInstanceConfiguration('dba_mgr_admin@192.0.2.12:3366');
dba.checkInstanceConfiguration('dba_mgr_admin@192.0.2.13:3366');
1
2
3
  1. 创建集群
var cluster = dba.createCluster('myMGR');
1

如果失败或报错需要重来:

dba.dropMetadataSchema();
1

⚠️ 这条只能在「刚创建失败、还没有任何业务数据」的实例上用。它会删掉 mysql_innodb_cluster_metadata 元数据库——在一个已在运行的集群上执行,等于把集群拓扑信息整个抹掉,Router 会立刻失去路由目标,且无法通过 dba.getCluster() 恢复,只能重新 createCluster 并逐个 addInstance。误操作代价极高,执行前先确认 cluster.status() 里没有任何在服务的节点。

  1. 添加节点
cluster.addInstance('dba_mgr_admin@192.0.2.12:3366');
1

选择默认克隆模式添加直接回车 重复以上操作添加所有节点

  1. 查看状态以下命令均可查看 首先定义var
var cluster = dba.getCluster()
1

然后执行

cluster.describe();
cluster.status();
cluster.status({extended:1});
1
2
3

# 部署MySQL Router,实现读写分离以及故障自动转移

MySQL Router是一个轻量级的中间件,它采用多端口的方案实现读写分离以及读负载均衡,而且同时支持mysql和mysql x协议。

mysqlrouter初始化 MySQL Router对应的服务器端程序文件是 /usr/bin/mysqlrouter,第一次启动时要先进行初始化

# 参数解释

参数 --bootstrap 表示开始初始化

参数 dba_mgr_admin@192.0.2.11:3366 是MGR集群管理员账号

--user=mysqlrouter 是运行mysqlrouter进程的系统用户名
[root@db-01]# mysqlrouter --bootstrap dba_mgr_admin@192.0.2.11:3366 --user=mysqlrouter

Please enter MySQL password for dba_admin: <-- 输入密码
# 然后mysqlrouter开始自动进行初始化
# 它会自动读取MGR的元数据信息,自动生成配置文件
1
2
3
4
5

4.2 启动mysqlrouter服务 这就初始化完毕了,按照上面的提示,直接启动 mysqlrouter 服务即可:

[root@db-01]# systemctl start mysqlrouter


检查
ps -ef | grep -v grep | grep mysqlrouter

netstat -lntp | grep mysqlrouter
1
2
3
4
5
6
7

mysqlrouter 初始化时自动生成的配置文件是 /etc/mysqlrouter/mysqlrouter.conf,主要是关于R/W、RO不同端口的配置

[routing:myCluster_rw]
bind_address=0.0.0.0
bind_port=6446
destinations=metadata-cache://myCluster/?role=PRIMARY
routing_strategy=first-available
protocol=classic
1
2
3
4
5
6

可以根据需要自行修改绑定的IP地址和端口。

4.3 确认读写分离效果 现在,用客户端连接到6446(读写)端口,确认连接的是PRIMARY节点:

[root@db-01]# mysql -h192.0.2.11 -u dba_mgr_admin -p -P6446

mysql>select @@server_uuid;
1
2
3

4.4 关闭ssl避免跟客户端应用不兼容通讯协议

分别登录mysqlrouter 的服务器,更改配置

 sudo vim /etc/mysqlrouter/mysqlrouter.conf

client_ssl_mode=DISABLED
server_ssl_mode=DISABLED
server_ssl_verify=DISABLED
1
2
3
4
5

分别重启mysqlrouter

sudo systemctl restart mysqlrouter.service
1

# 验证:集群是不是真的可用

cluster.status() 返回 OK 只说明元数据层面没问题,还要确认三件事。

1. 三个节点都 ONLINE,且集群容错度正确

cluster.status();
1

预期输出(关注 status 与 statusText):

{
    "clusterName": "myMGR",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "192.0.2.11:3366",
        "status": "OK",
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
        "topology": {
            "192.0.2.11:3366": {"memberRole": "PRIMARY",   "status": "ONLINE"},
            "192.0.2.12:3366": {"memberRole": "SECONDARY", "status": "ONLINE"},
            "192.0.2.13:3366": {"memberRole": "SECONDARY", "status": "ONLINE"}
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

can tolerate up to ONE failure 这句是关键——3 节点只能容忍挂 1 个。如果显示 Cluster is NOT tolerant to any failures,说明只有 2 个节点在线,此时再挂一个就会因失去多数派而整组不可写。

也可以直接从 MySQL 侧看:

SELECT MEMBER_HOST, MEMBER_PORT, MEMBER_STATE, MEMBER_ROLE
FROM performance_schema.replication_group_members;
1
2

2. Router 确实路由到了 PRIMARY,且 6447 是只读的

# 6446 读写口,应该连到 PRIMARY
mysql -h 192.0.2.11 -P6446 -u dba_mgr_admin -p -e "SELECT @@hostname, @@read_only;"
# 6447 只读口,应该连到 SECONDARY 且 read_only=1
mysql -h 192.0.2.11 -P6447 -u dba_mgr_admin -p -e "SELECT @@hostname, @@read_only;"
1
2
3
4

预期 6446 返回 read_only = 0、6447 返回 read_only = 1。两个口返回同一台机器,说明 bootstrap 时读到的元数据不对,需要重新 bootstrap。

3. 真的切一次主(没演练过的高可用不算高可用)

cluster.setPrimaryInstance('192.0.2.12:3366');
cluster.status();
1
2

切完立刻再跑一遍第 2 步——Router 应当在几秒内自动把 6446 指向新 PRIMARY,应用无需改配置。这一步是整个部署里唯一能证明「高可用真的成立」的验证,不要跳过。

# 坑与边界

  • 组通信端口没放行 → 节点永远停在 RECOVERING。 最高频的问题,见前面「网络调整」一节。判断方法:SELECT * FROM performance_schema.replication_group_member_stats; 看不到该节点,或错误日志里反复出现 [GCS] Connection attempt from IP address ... refused。

  • MGR 有硬性前置条件,不满足会在 createCluster 时才报错:必须 gtid_mode=ON、enforce_gtid_consistency=ON、binlog_format=ROW、每个节点 server_id 唯一、且所有表必须有主键或非空唯一键(无主键表会让写入直接失败)。dba.configureInstance() 会检查前几项,但查不出无主键表,建集群前自己扫一遍:

    SELECT t.TABLE_SCHEMA, t.TABLE_NAME
    FROM information_schema.TABLES t
    LEFT JOIN information_schema.TABLE_CONSTRAINTS c
      ON c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME AND c.CONSTRAINT_TYPE = 'PRIMARY KEY'
    WHERE c.CONSTRAINT_NAME IS NULL
      AND t.TABLE_SCHEMA NOT IN ('sys','mysql','performance_schema','information_schema')
      AND t.TABLE_TYPE = 'BASE TABLE';
    
    1
    2
    3
    4
    5
    6
    7
  • 单主模式下 SECONDARY 是 super_read_only=ON,这是 MGR 自己设的,不要手工关掉——关掉之后往 SECONDARY 写入会造成组内数据分叉,节点会被踢出组且只能重新加入。

  • 多数派是硬约束。3 节点挂 2 个,剩下那个不会自动接管,整组进入不可写状态(ERROR 3101)。这是设计如此,不是故障。确认无法恢复另外两个节点时,才用 group_replication_force_members 强制重组——这条命令有脑裂风险,属于最后手段。

  • 大事务会被拒绝。group_replication_transaction_size_limit 默认 150MB,超过的事务直接报错回滚。批量导数据前要么分批,要么临时调大该参数。

  • 关闭 Router 的 SSL 是降级操作。文中 4.4 关 SSL 是为了兼容老客户端,代价是集群与应用之间的流量变成明文。只在内网且确认客户端不支持时才做,能改客户端就别关。

  • --bootstrap 生成的配置会在集群拓扑变化时自动更新,手工改过的 mysqlrouter.conf 可能被覆盖。要定制配置,改完记得记录,重新 bootstrap 后需要再改一遍。

#集群运维#MySQL
上次更新: 9/11/2026

← MySQL锁 OPTIMIZE TABLE 和 ANALYZE TABLE 的区别:用实测数据说话→

最近更新
01
DeepSeek Harness 实战 06|学习笔记:插件、工具、技能不在同一个维度上 原创
09-11
02
DeepSeek Harness 实战 05|让两个编码 Agent 共用一份长期记忆 原创
09-09
03
DeepSeek Harness 实战 04|学习笔记:从「已知限制」里读出三处设计张力 原创
09-08
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式