MySQL主从搭建
1.机器规划
# 单台虚拟机 192.168.239.128:3306 master 192.168.239.128:3307 slave1 192.168.239.128:3308 slave2
2.目录规划
# 相关目录 /usr # 存放系统自带的软件包 通过系统包管理器(如 yum、apt)安装的软件 /usr/local # 存放本地编译安装的软件 管理员手动编译安装的程序 /usr/local/src # 存放本地编译安装的软件源码 软件包和源代码的存储位置 /opt # 存放第三方打包的独立软件 例如 mysql-xxx.tar.xz 解压后的软件 # 规划 /usr/local/src # 压缩包mysql-xxx.tar.xz /usr/local/ # 解压包 /etc/mysql/3306/my.cnf # 配置文件 /data/3306/data/ # 数据文件
清理环境
1.停止 MySQL 服务
# 查找并停止所有 MySQL 服务 ps -ef | grep mysql # 如果有 systemd 服务 systemctl stop mysqld # 强制终止 MySQL 进程 pkill mysql
2.删除所有 MySQL 相关目录
find / -name mysql find / -name mysqld # 删除找到的所有 mysql 目录和文件 rm -rf /usr/local/mysql rm -rf /home/yungu/mysql-8.0.24-linux-glibc2.12-x86_64 rm -rf /usr/lib64/mysql rm -rf /usr/share/mysql rm -f /etc/init.d/mysqld # 删除服务相关文件 rm -f /run/lock/subsys/mysql # 删除数据相关文件 rm -rf /data
3.删除配置文件
find / -name my*.cnf # 删除可能的配置文件 rm -f /etc/my.cnf rm -f /etc/my.cnf.d/* rm -rf /etc/my.cnf.d/ rm -f /etc/systemd/system/mysqld.service
4.删除用户和组
# 删除 mysql 用户和组(如果存在) id mysql >/dev/null 2>&1 && userdel mysql getent group mysql >/dev/null 2>&1 && groupdel mysql # 1. 检查 mysql 用户是否存在 # 2. 如果存在(id 命令成功)→ 删除该用户 # 3. 如果不存在(id 命令失败)→ 不执行删除操作
5.删除环境变量
vim /etc/profile # 重新加载 /etc/profile source /etc/profile # 重新加载 systemd 配置 systemctl daemon-reload
下载安装包
1.地址
https://dev.mysql.com/downloads/mysql/
2.选择
Product Version: 8.4.6 LTS Operating System: Linux-Generic OS Version: Linux-Generic(glibc 2.17)(x86,64-bit) CPU架构:x86, 64-bit 包类型:Compressed TAR Archive Archived Versions : 存档版本 Innovation Release 创新版 LTS Release 长期支持版 (Long Term Support)
3.mysql版本
GA (General Availability):正式发布版,生产可用 RC (Release Candidate):发布候选版,接近正式版 DMR (Development Milestone Release):开发里程碑版本 Beta:测试版 Alpha:早期测试版
4.glibc版本
# 查看 CentOS 7.9 系统中的 glibc 版本 # ldd 是 Linux 系统中的一个命令行工具,用于显示动态链接库的依赖关系。 ldd --version #使用 rpm 查询 glibc 版本 rpm -q glibc
5.下载后上传服务器
yum install -y lrzsz cd /usr/local/src #上传 rz #两个文件 mysql-8.4.6-linux-glibc2.17-x86_64.tar.xz # MySQL 软件包 mysql-8.4.6-linux-glibc2.17-x86_64.tar.xz.asc # GPG 签名文件 用不到 #md5验证 #计算文件的 MD5 值 md5sum mysql-8.4.6-linux-glibc2.17-x86_64.tar.xz # 计算结果和官方给的值相同即正确 MD5: 51b6576dedc974e255461cbefa246785 Size: 869.6M
6.图片
安装
1.创建用户组和用户
#添加Linux组(可选) groupadd mysql #添加linux组员 即用户 (可选) useradd -r -g mysql -s /bin/false mysql
2.解压缩
#解压 tar xvf /usr/local/src/mysql-8.4.6-linux-glibc2.17-x86_64.tar.xz -C /usr/local/ #软链接 #必须全路径 ln -s /usr/local/mysql-8.4.6-linux-glibc2.17-x86_64 /usr/local/mysql
3.环境变量
# 修改环境变量 vi /etc/profile 末尾加 export PATH=/usr/local/mysql/bin:$PATH # 测试环境变量 mysql -V
4.创建数据目录
# 创建数据目录 mkdir -p /data/330{6..8}/data # 创建日志目录 #注意: 日志和数据分开存储 mkdir -p /data/330{6..8}/log # 授权 chown -R mysql.mysql /data/*
5.创建配置文件
# 创建配置文件 vi /etc/mysql/3306/my.cnf vi /etc/mysql/3307/my.cnf vi /etc/mysql/3308/my.cnf
[mysqld] # MySQL 服务端配置 # 基本路径配置 basedir=/usr/local/mysql # MySQL 安装目录 datadir=/data/3306/data # 数据文件存储目录 socket=/tmp/mysql3306.sock # Unix socket 文件路径(本地连接可使用) # 网络配置 server_id=51 # 服务器唯一标识 port=3306 # TCP/IP 连接使用的端口号 # 日志配置 log_error=/data/3306/log/mysql-err.log # 错误日志的存储位置 log_bin=/data/3306/log/mysql-bin # 二进制日志文件目录的存储位置 binlog_format=row # 设置二进制日志格式 ROW 模式记录每行数据的变化 slow_query_log=1 # 慢查询日志开关:1启用 slow_query_log_file=/data/3306/log/slow.log # 慢查询日志文件的存储位置 general_log=on # 普通日志开关:on启用 general_log_file=/data/3306/log/genlog # 普通日志文件的存储位置 # 安全配置 secure-file-priv=/tmp # 限制文件操作的目录LOAD DATA INFILE 和 SELECT ... INTO OUTFILE # 用户配置(重要) user=mysql # 指定 MySQL 服务运行的系统用户(限制mysql进程对系统的访问权限) # GTID 配置 gtid-mode=off # 关闭 GTID(全局事务标识)不使用 GTID 复制模式 enforce-gtid-consistency=off [mysql] # MySQL 客户端配置 socket=/tmp/mysql3306.sock prompt=db01 # 设置 MySQL 客户端命令行提示符为 "db01"
进程1
[mysqld] basedir=/usr/local/mysql datadir=/data/3306/data socket=/tmp/mysql3306.sock server_id=51 port=3306 log_error=/data/3306/log/mysql-err.log log_bin=/data/3306/log/mysql-bin slow_query_log=1 slow_query_log_file=/data/3306/log/slow.log general_log=on general_log_file=/data/3306/log/genlog secure-file-priv=/tmp user=mysql gtid-mode=off enforce-gtid-consistency=off [mysql] socket=/tmp/mysql3306.sock prompt=db01
进程2
[mysqld] basedir=/usr/local/mysql datadir=/data/3307/data socket=/tmp/mysql3307.sock server_id=52 port=3307 log_error=/data/3307/log/mysql-err.log log_bin=/data/3307/log/mysql-bin slow_query_log=1 slow_query_log_file=/data/3307/log/slow.log general_log=on general_log_file=/data/3307/log/genlog secure-file-priv=/tmp user=mysql gtid-mode=off enforce-gtid-consistency=off [mysql] socket=/tmp/mysql3307.sock prompt=db02
进程3
[mysqld] basedir=/usr/local/mysql datadir=/data/3308/data socket=/tmp/mysql3308.sock server_id=53 port=3308 log_error=/data/3308/log/mysql-err.log log_bin=/data/3308/log/mysql-bin slow_query_log=1 slow_query_log_file=/data/3308/log/slow.log general_log=on general_log_file=/data/3308/log/genlog secure-file-priv=/tmp user=mysql gtid-mode=off enforce-gtid-consistency=off [mysql] socket=/tmp/mysql3308.sock prompt=db03
6.初始化
# 初始化 MySQL 实例 # --defaults-file:指定配置文件路径 # --initialize-insecure:初始化数据库,不生成临时 root 密码 # 1.创建数据目录结构 2.初始化系统表 3.创建默认用户(root 用户无密码) mysqld --defaults-file=/etc/mysql/3306/my.cnf --initialize-insecure mysqld --defaults-file=/etc/mysql/3307/my.cnf --initialize-insecure mysqld --defaults-file=/etc/mysql/3308/my.cnf --initialize-insecure
7.启动
# 启动方式一 # 安全启动 MySQL 服务 # --defaults-file:指定配置文件路径 # &:后台运行 mysqld_safe --defaults-file=/etc/mysql/3306/my.cnf & mysqld_safe --defaults-file=/etc/mysql/3306/my.cnf & mysqld_safe --defaults-file=/etc/mysql/3306/my.cnf & # 验证 netstat -tulnp|grep mysqld # 启动方式二 # 通过系统服务脚本管理 传统的 init.d 方式 /etc/init.d/mysqld restart # 启动方式三 : systemd方式 # 使用系统服务管理(稳定) systemctl enable mysqld systemctl start mysqld # 启动方式四 : SYS-V启动方式 cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld service mysqld restart # 启动方式四 ./usr/local/mysql.server start
8.本地连接
# 通过 socket 连接 MySQL # -S:指定 socket 文件路径 # mysql.sock:特定实例的 socket 文件 mysql -S /tmp/mysql3306.sock mysql -S /tmp/mysql3307.sock mysql -S /tmp/mysql3308.sock
日志
错误日志(error log): 记录 启动故障 主从故障 死锁数据库hang,堆栈信息 二进制日志(binlog): 记录了MySQL 发生过的修改的操作的日志。除了show select。 慢日志(slow log): 记录MySQL工作中,运行较慢的语句。 普通日志(general_log): 记录MySQL运行期间,所有的所作语句 # 错误日志设置 #查询错误日志记录级别 show variables like '%log_error%'; #设置日志记录级别 set global log_error_verbosity=3; # 慢日志设置 -- 查看慢查询日志状态 SHOW VARIABLES LIKE 'slow_query_log%'; -- 查看慢查询相关参数 SHOW VARIABLES LIKE '%slow%'; -- 查看慢查询统计 SHOW GLOBAL STATUS LIKE '%slow%'; #开关: [mysqld] slow_query_log=1 # 开关:1启用 slow_query_log_file=/data/3306/log/slow.log # 指定慢查询日志文件的存储位置 #维度: [mysqld] set global slow_query_log=1 # 开启慢查询日志 set global long_query_time=1.0 # 设置慢查询阈值 1秒 set global log_queries_not_using_indexes=1 # 即使查询执行很快,但没有使用索引也会被记录 set global log_throttle_queries_not_using_indexes=1000; #每分钟最多记录 1000 条未使用索引的查询,防止日志文件过大
综合成本与稳定性
MHA(Master High Availability)基于传统主从复制的外置高可用工具(Perl开发),核心解决主库故障时的自动切换问题,需配合半同步/异步复制使用。
ProxySQL 是一个高性能的 MySQL 代理,支持动态查询路由、负载均衡、连接池等功能,非常适用于读写分离。
金融级强一致
InnoDB Cluster确实是基于
MySQL Group Replication(MGR)`构建的。
对于三甲医院这类对数据一致性和系统稳定性要求极高的场景,Single-Primary 模式提供了更可靠和可维护的解决方案。
MGR(MySQL Group Replication):MySQL内核集成的分布式强一致方案(C/C++开发),通过组复制协议实现多节点数据实时同步与自愈,是官方新一代高可用架构基础。
MySQL Router : MySQL 官方提供的轻量级代理,专为 MySQL InnoDB Cluster 和 读写分离 设计,能够实现自动路由和高可用性支持。
应用层
↓
MySQL Server 层
↓
Group Communication System (GCS) 层
↓
XCom 层 (Paxos算法)
IP | HOSTNAME | ROLE | soft |
127.0.0.1 | master | mic-master | mysql、mysqlsh |
127.0.0.1 | slave1 | mic-slave1 | mysql、mysqlsh |
127.0.0.1 | slave2 | mic-slave2 | mysql、mysqlsh |
127.0.0.1 | manager | mic-manager | mysqlsh、mysql-router |
mysql-8.4.6-linux-glibc2.17-x86_64.tar.xz mysql-router-8.4.6-linux-glibc2.17-x86_64.tar.xz mysql-shell-8.4.6-linux-glibc2.17-x86-64bit.tar.gz
#解压缩 # 第一步:解压 xz 压缩 xz -d /usr/local/src/mysql-8.4.6-linux-glibc2.17-x86_64.tar.xz # 第二步:解压 tar 归档 tar xf /usr/local/src/mysql-8.4.6-linux-glibc2.17-x86_64.tar -C /usr/local/ xz -d /usr/local/src/mysql-router-8.4.6-linux-glibc2.17-x86_64.tar.xz tar xf /usr/local/src/mysql-router-8.4.6-linux-glibc2.17-x86_64.tar -C /usr/local/ tar xf /usr/local/src/mysql-shell-8.4.6-linux-glibc2.17-x86-64bit.tar.gz -C /usr/local/ #软链接 ln -s /usr/local/mysql-8.4.6-linux-glibc2.17-x86_64/ /usr/local/mysql ln -s /usr/local/mysql-shell-8.4.6-linux-glibc2.17-x86-64bit/ /usr/local/mysqlsh ln -s /usr/local/mysql-router-8.4.6-linux-glibc2.17-x86_64/ /usr/local/mysql-router
# 添加域名 vim /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 master slave1 slave2 manage ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 # 测试主机名解析 ping master nslookup master getent hosts master # 如果未生效 # 重启网络服务(某些发行版) sudo systemctl restart network
vim /etc/mysql/3306/my.cnf
[mysqld] # MySQL 服务端配置 # 基本路径配置 basedir=/usr/local/mysql # MySQL 安装目录 datadir=/data/3306/data # 数据文件存储目录 socket=/tmp/mysql3306.sock # Unix socket 文件路径(本地连接可使用) # 网络配置 server_id=51 # 服务器唯一标识 port=3306 # TCP/IP 连接使用的端口号 # 日志配置 log_error=/data/3306/log/mysql-err.log # 错误日志的存储位置 log_bin=/data/3306/log/mysql-bin # 二进制日志文件目录的存储位置 binlog_format=row # 设置二进制日志格式 ROW 模式记录每行数据的变化 slow_query_log=1 # 慢查询日志开关:1启用 slow_query_log_file=/data/3306/log/slow.log # 慢查询日志文件的存储位置 general_log=on # 普通日志开关:on启用 general_log_file=/data/3306/log/genlog # 普通日志文件的存储位置 # 安全配置 secure-file-priv=/tmp # 限制文件操作的目录LOAD DATA INFILE 和 SELECT ... INTO OUTFILE # 用户配置(重要) user=mysql # 指定 MySQL 服务运行的系统用户(限制mysql进程对系统的访问权限) # GTID 配置 gtid-mode=ON # 启用 GTID(全局事务标识)复制模式 enforce-gtid-consistency=ON # 强制 GTID 一致性 # 复制 #master_info_repository=TABLE # 将主库信息存储在表中而非文件。 8.3已移除 #relay_log_info_repository=TABLE # 将中继日志信息存储在表中。8.3已移除 log_slave_updates=ON # 从服务器会记录它执行的更新到自己的二进制日志中。 # Group Replication 配置 loose-group_replication_group_name="707df9a6-e6af-4140-bbbd-ccae9f7138f6" # UUID 组复制群组名称。 loose-group_replication_start_on_boot=OFF # 启动时不自动启动组复制。 loose-group_replication_local_address="master:3306" # 本地用于组复制通信的地址和端口。 loose-group_replication_group_seeds="master:3306,slave1:3307,slave2:3308" # 种子成员列表。 loose-group_replication_bootstrap_group=OFF # 不引导新组。 loose-group_replication_ip_whitelist="master,slave1,slave2,manager" # 白名单 IP 或主机名。 # X Plugin 保持启用但指定端口 mysqlx_port=33060 mysqlx_bind_address=0.0.0.0 [mysql] # MySQL 客户端配置 socket=/tmp/mysql3306.sock prompt=db01 # 设置 MySQL 客户端命令行提示符为 "db01"
[mysqld] basedir=/usr/local/mysql datadir=/data/3307/data socket=/tmp/mysql3307.sock server_id=52 # 差异 port=3307 log_error=/data/3307/log/mysql-err.log log_bin=/data/3307/log/mysql-bin binlog_format=row slow_query_log=1 slow_query_log_file=/data/3307/log/slow.log general_log=on general_log_file=/data/3307/log/genlog secure-file-priv=/tmp user=mysql gtid-mode=ON enforce-gtid-consistency=ON log_slave_updates=ON loose-group_replication_group_name="397752c1-be40-42bb-ba45-216f1407d950" # 差异 loose-group_replication_start_on_boot=OFF loose-group_replication_local_address="slave1:3307" # 差异 loose-group_replication_group_seeds="master:3306,slave1:3307,slave2:3308" loose-group_replication_bootstrap_group=OFF loose-group_replication_ip_whitelist="master,slave1,slave2,manager" loose-group_replication_allow_local_disjoint_gtids_join=ON # 从节点特有配置,允许GTID不连续的节点加入复制组 mysqlx_port=33070 mysqlx_bind_address=0.0.0.0 [mysql] socket=/tmp/mysql3307.sock prompt=db02
[mysqld] basedir=/usr/local/mysql datadir=/data/3308/data socket=/tmp/mysql3308.sock server_id=53 port=3308 log_error=/data/3308/log/mysql-err.log log_bin=/data/3308/log/mysql-bin binlog_format=row slow_query_log=1 slow_query_log_file=/data/3308/log/slow.log general_log=on general_log_file=/data/3308/log/genlog secure-file-priv=/tmp user=mysql gtid-mode=ON enforce-gtid-consistency=ON log_slave_updates=ON loose-group_replication_group_name="10b74154-09a3-46d2-8060-6a1c659ac5d2" loose-group_replication_start_on_boot=OFF loose-group_replication_local_address="slave2:3308" loose-group_replication_group_seeds="master:3306,slave1:3307,slave2:3308" loose-group_replication_bootstrap_group=OFF loose-group_replication_ip_whitelist="master,slave1,slave2,manager" loose-group_replication_allow_local_disjoint_gtids_join=ON mysqlx_port=33080 mysqlx_bind_address=0.0.0.0 [mysql] socket=/tmp/mysql3308.sock prompt=db03
pkill mysqld pkill mysqlsh rm -rf /data/330{6~8}/data/* rm -rf /data/330{6~8}/log/* # 设置正确的所有者和权限 chown -R mysql:mysql /data/* chmod -R 755 /data/* # 使用mysql用户初始化数据库 sudo -u mysql /usr/local/mysql/bin/mysqld --defaults-file=/etc/mysql/3306/my.cnf --initialize-insecure sudo -u mysql /usr/local/mysql/bin/mysqld --defaults-file=/etc/mysql/3307/my.cnf --initialize-insecure sudo -u mysql /usr/local/mysql/bin/mysqld --defaults-file=/etc/mysql/3308/my.cnf --initialize-insecure
sudo -u mysql /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/mysql/3306/my.cnf & sudo -u mysql /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/mysql/3307/my.cnf & sudo -u mysql /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/mysql/3308/my.cnf &
# 验证 netstat -tulnp | grep mysqld tail -f /data/3306/log/mysql-err.log
# 通过 socket 连接 MySQL # 首次无密码连接 sudo -u mysql /usr/local/mysql/bin/mysql -S /tmp/mysql3306.sock sudo -u mysql /usr/local/mysql/bin/mysql -S /tmp/mysql3307.sock sudo -u mysql /usr/local/mysql/bin/mysql -S /tmp/mysql3308.sock # 设置root@'localhost'密码 ALTER USER 'root'@'localhost' IDENTIFIED BY '123456'; # 再次连接 sudo -u mysql /usr/local/mysql/bin/mysql -S /tmp/mysql3306.sock -p123456 sudo -u mysql /usr/local/mysql/bin/mysql -S /tmp/mysql3307.sock -p123456 sudo -u mysql /usr/local/mysql/bin/mysql -S /tmp/mysql3308.sock -p123456
# 以 root 用户 通过 socket 连接 MySQL /usr/local/mysql/bin/mysql -S /tmp/mysql3306.sock -p123456 /usr/local/mysql/bin/mysql -S /tmp/mysql3307.sock -p123456 /usr/local/mysql/bin/mysql -S /tmp/mysql3308.sock -p123456 /** 为每一个mysql实例创建一个专门用于集群管理的新用户 clusteradmin 更安全的做法 只授予必要的最小权限 测试可以不设置 */ CREATE USER 'clusteradmin'@'%' IDENTIFIED BY '123456'; GRANT ALL PRIVILEGES ON *.* TO 'clusteradmin'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES;
2.11 MySQL Shell 组建管理集群
什么是 MySQL Shell? MySQL 官方提供的新一代命令行客户端工具 支持多种编程语言模式:JavaScript、Python、SQL 专为 MySQL 8.0+ 设计,支持现代 MySQL 功能 提供 DBA 管理和开发功能
doc: https://dev.mysql.com/doc/mysql-shell/8.4/en/mysqlsh.html
# 1.mysql shell 工具分别连接3个MySQL实例 # 以 root 用户身份运行 MySQL Shell 并连接到 MySQL 实例 (3306) 【TCP/IP 协议】 /usr/local/mysqlsh/bin/mysqlsh --uri=root@localhost:3306 # 以 clusteradmin 用户身份运行 /usr/local/mysqlsh/bin/mysqlsh --uri=clusteradmin@localhost:3306 # 以 root 用户身份运行 MySQL Shell 并连接到 MySQL 实例 (3306) 【指定 socket 连接】 # 使用 Unix Socket 文件直接连接,绕过网络协议栈 /usr/local/mysqlsh/bin/mysqlsh -S /tmp/mysql3306.sock -p123456 /usr/local/mysqlsh/bin/mysqlsh -u root -h localhost -P 3306 -S /tmp/mysql3306.sock -p123456 # 在 MySQL Shell 中切换到 JavaScript 模式 \js # 查看当前状态 \status # 查看 DBA 模块帮助 dba.help() # 退出 \exit # 2. 初始化配置集群实例 dba.configureInstance('clusteradmin@localhost:3306') 这个命令会检查并自动配置实例以满足 InnoDB Cluster 的要求 包括: 创建必要的用户和权限 配置 GTID 设置二进制日志 配置其他集群所需的参数 # 3. 创建 InnoDB Cluster var cluster = dba.createCluster('myCluster') # 4. 检查实例状态 dba.checkInstanceConfiguration("clusteradmin@localhost:3306"); # 5. 查看集群状态(创建集群后) cluster.status() # 6. 集群结构信息描述 cluster.describe() # 7. 集群状态总览 cluster.status() # 8. 查看集群名字 dba.getCluster(); # 9. 查看router信息 cluster.listRouters() # 10.将实例重新加入到集群 如果实例离开集群,比如丢失连接,并且没有自动重新加入集群。 Cluster.rejoinInstance() # 11.在线切换primary 实例 cluster.setPrimaryInstance('clusteradmin@slave1:3306')
[root@localhost ~]# /usr/local/mysqlsh/bin/mysqlsh --uri=clusteradmin@master:3306 MySQL localhost:3308 ssl SQL > \js MySQL localhost:3308 ssl JS > dba.configureInstance('clusteradmin@master:3306') # 初始化配置 MySQL localhost:3308 ssl JS > dba.checkInstanceConfiguration("clusteradmin@master:3306"); MySQL localhost:3308 ssl JS > \q
3307实例-从节点
[root@localhost ~]# /usr/local/mysqlsh/bin/mysqlsh --uri=clusteradmin@slave1:3307 MySQL localhost:3308 ssl SQL > \js MySQL localhost:3308 ssl JS > dba.configureInstance('clusteradmin@slave1:3307') # 初始化配置 MySQL localhost:3308 ssl JS > dba.checkInstanceConfiguration("clusteradmin@slave1:3307"); MySQL localhost:3308 ssl JS > \q
3308实例-从节点
[root@localhost ~]# /usr/local/mysqlsh/bin/mysqlsh --uri=clusteradmin@slave2:3308 MySQL localhost:3308 ssl SQL > \js MySQL localhost:3308 ssl JS > dba.configureInstance('clusteradmin@slave2:3308') # 初始化配置 MySQL localhost:3308 ssl JS > dba.checkInstanceConfiguration("clusteradmin@slave2:3308"); MySQL localhost:3308 ssl JS > \q
2.14 创建集群并添加节点
添加主节点
#3306实例 [root@localhost ~]# /usr/local/mysqlsh/bin/mysqlsh --uri=clusteradmin@master:3306 MySQL localhost:3308 ssl SQL > \js MySQL localhost:3308 ssl JS > var cluster = dba.createCluster('myCluster') # 创建集群 MySQL localhost:3308 ssl JS > cluster.status() MySQL localhost:3308 ssl JS > \q
添加slave1\slave2节点
#3307实例 [root@localhost ~]# /usr/local/mysqlsh/bin/mysqlsh --uri=clusteradmin@localhost:3307 MySQL localhost:3308 ssl SQL > \js MySQL localhost:3308 ssl JS > shell.connect('clusteradmin@master:3306'); # 连接主节点 MySQL localhost:3308 ssl JS > var cluster = dba.getCluster('myCluster') # 获取集群实例 MySQL localhost:3308 ssl JS > cluster.addInstance('clusteradmin@slave1:3307'); # 添加从节点 MySQL localhost:3308 ssl JS > cluster.addInstance('clusteradmin@slave2:3308'); # 添加从节点 MySQL localhost:3308 ssl JS > cluster.status()
2.15 MySQL Router 集群路由
doc: https://dev.mysql.com/doc/mysql-router/8.4/en/
初始化配置
# 注册router到集群,生成myrouter目录, 并生成启动程序和配置文件. /usr/local/mysql-router/bin/mysqlrouter --bootstrap clusteradmin@master:3306 -d /etc/mysqlrouter --user=root 各参数含义: /usr/local/mysql-router/bin/mysqlrouter:MySQL Router可执行程序 --bootstrap clusteradmin@master:3306: --bootstrap:引导模式,自动配置Router clusteradmin@master:3306:连接到MySQL集群的账户和地址 clusteradmin:用户名 master:主机名 3306:端口号 -d /etc/mysqlrouter: -d:指定工作目录 myrouter:创建的目录名,包含配置文件和运行时数据 --user=root:指定MySQL Router运行时使用的系统用户 /** After this MySQL Router has been started with the generated configuration $ /usr/local/mysql-router/bin/mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf InnoDB Cluster 'myCluster' can be reached by connecting to: ## MySQL Classic protocol # 传统MySQL协议 - Read/Write Connections: localhost:6446 # 读写端口 - Read/Only Connections: localhost:6447 # 只读端口 - Read/Write Split Connections: localhost:6450 # 读写分离端口 自动路由,写操作到Primary,读操作到Secondary ## MySQL X protocol # X协议 - Read/Write Connections: localhost:6448 - Read/Only Connections: localhost:6449 */
启动
# 启动 router /etc/mysqlrouter/start.sh
验证
# 验证连接 router # 1.本机mysql-shell连接 /usr/local/mysqlsh/bin/mysqlsh --uri root@localhost:6446 # 2.本机mysql连接 /usr/local/mysql/bin/mysql -h 127.0.0.1 -u root -P 6446 -p
高可用
MySQL Router进程确实可能会挂掉,而且在生产环境中确实需要考虑高可用性。 MySQL Router高可用方案: # 方案一:负载均衡器 + 多个Router实例 # 部署架构 Load Balancer (HAProxy/Nginx/F5) ├── Router Node 1 (port 6446/6447) ├── Router Node 2 (port 6446/6447) └── Router Node 3 (port 6446/6447) # 方案二:Keepalived + 多个Router实例 # 主Router节点 VIP: 192.168.1.100 Router1: 192.168.1.101 Router2: 192.168.1.102 应用服务器 ↓ 负载均衡器 (HAProxy/Nginx) ↓ 多个MySQL Router实例 ↓ MySQL InnoDB Cluster
1.登陆后,新建一个表,往里面写进数据,查看从节点数据会不会同步; 2.关闭master的mysql服务,route将主节点自动切换到slave1,slave1从只读变为可读写,再重新启动 master mysql后,master变为只读模式。 (验证MySQL InnoDB Cluster的自动故障转移和恢复机制。) 3. 验证读写分离功能
验证同步
主
# 通过MySQL Router的读写端口连接 [root@localhost ~]# /usr/local/mysql/bin/mysql -h master -u root -P 6446 -p
-- 选择或创建测试数据库 CREATE DATABASE IF NOT EXISTS test_db; USE test_db; -- 创建测试表 CREATE TABLE test_table ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 插入测试数据 INSERT INTO test_table (name) VALUES ('Test Record 1'), ('Test Record 2'), ('Test Record 3'); -- 提交事务(如果需要) COMMIT; -- 查看插入的数据 SELECT * FROM test_table;
从
# 连接到从节点验证同步 # 通过MySQL Router的只读端口连接 [root@localhost ~]# mysql -h localhost -P 6447 -u clusteradmin -p -- 使用相同数据库 USE test_db; -- 查看数据是否同步 SELECT * FROM test_table; -- 查看当前节点状态 SELECT @@server_id, @@hostname, @@port; SELECT * FROM performance_schema.replication_group_members;
监控主
# 实时监控同步状态(主节点) -- 确认当前连接的是主节点 SELECT @@server_id, @@hostname, @@port; -- 查看集群状态 Group Replication SELECT * FROM performance_schema.replication_group_members; -- 查看复制延迟(如果有的话) SELECT * FROM performance_schema.replication_applier_status; -- 查看事务应用情况 SELECT CHANNEL_NAME, VIEW_ID, MEMBER_ID, COUNT_TRANSACTIONS_IN_QUEUE, COUNT_TRANSACTIONS_CHECKED, COUNT_CONFLICTS_DETECTED, COUNT_TRANSACTIONS_ROWS_VALIDATING FROM performance_schema.replication_group_member_stats; -- 检查是否有错误 SHOW REPLICA STATUS\G -- 检查错误日志 SHOW ENGINE INNODB STATUS\G -- 查看read_only状态 (0:可读写模式 1:只读模式) SELECT @@super_read_only as super_read_only; -- 查看所有只读相关变量 SHOW VARIABLES LIKE '%read_only%'; -- 查看当前用户权限 SHOW GRANTS;
验证故障转移
1. 初始状态 Master (可读写): master:3306 Slave1 (只读): slave1:3307 Slave2 (只读): slave2:3308 MySQL Router: 读写端口6446 -> master, 只读端口6447 -> slaves 2. 关闭Master MySQL服务 [root@localhost ~]# /usr/local/mysql/bin/mysqladmin -u root -p -P 3306 -h master shutdown Group Replication检测到故障: 其他节点检测到Master节点失联 触发选举机制选择新的Primary节点 Slave1被选举为新的Primary节点 3. 新状态 Master (原Slave1, 现在可读写): slave1:3307 Slave1 (原Master, 已关闭): master:3306 Slave2 (只读): slave2:3308 MySQL Router: 读写端口6446 -> slave1, 只读端口6447 -> slave2 4. 重新启动原Master节点 [root@localhost ~]# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/mysql/3306/my.cnf & 原Master节点启动后自动重新加入Group Replication 但是角色变为Secondary(只读) 数据会自动同步到最新状态 5. 自动恢复过程 Master (新Primary): slave1:3307 (可读写) Slave1 (原Master): master:3306 (只读) Slave2: slave2:3308 (只读) MySQL Router: 读写端口6446 -> slave1, 只读端口6447 -> master,slave2
# 清空集群 [root@localhost ~]# /usr/local/mysqlsh/bin/mysqlsh --uri=clusteradmin@master:3306 MySQL localhost:3308 ssl SQL > \js MySQL localhost:3308 ssl SQL > shell.connect('clusteradmin@master:3306'); # 连接到集群 MySQL localhost:3308 ssl SQL > var cluster = dba.getCluster('myCluster') # 获取集群对象 MySQL localhost:3308 ssl SQL > cluster.removeInstance('slave1:3307') # 移除 slave1 实例 MySQL localhost:3308 ssl SQL > dba.dropMetadataSchema() # 清理损坏或不一致的集群配置 cluster.removeInstance() 的作用是: 1.从集群中移除指定节点: 停止该节点的 Group Replication 将该节点从集群成员列表中删除 该节点不再参与集群的数据同步 2.不影响被移除节点的数据: 节点上的数据不会被自动删除 节点仍然可以独立运行(作为单机MySQL) 3.集群继续运行: 剩余节点继续组成集群 如果移除的是主节点,集群会自动选举新的主节点 注意事项: 不能移除当前连接的实例(即不能移除自己) 需要确保集群有足够多的节点保持法定人数 建议在维护窗口期间执行此操作 特注: 已移除的InnoDB集群无法重新添加到InnoDB ClusterSet部署中。 如果想再次在该部署中使用服务器实例,需要使用它们重新设置一个新的集群。 dba.dropMetadataSchema() 命令的作用是删除 MySQL Shell 的元数据模式(metadata schema)。 具体作用: 1.删除元数据Schema 删除名为 mysql_innodb_cluster_metadata 的数据库 这个schema存储了InnoDB集群的配置和元数据信息 2.清除集群配置信息 删除集群的拓扑结构信息 清除实例角色(主节点/从节点)信息 移除集群成员列表 删除集群配置参数 警告: 此操作不可逆 会完全删除集群的配置信息 不影响用户数据,但会影响集群功能 执行前需要确保已经备份重要配置
网络拓扑
三台mysql连接交换机,交换机连接路由器
MySQL Server 1 MySQL Server 2 MySQL Server 3 | | | --------交换机(Switch)---------- | 路由器(Router) | 外部网络
MySQL1 → 交换机 → MySQL2
(局域网内部通信)