5. MySQL 数据库主从、高可用详解

MySQL 数据库主从、高可用详解

一、主从复制

1.1 主从同步原理

主从复制核心由 3 个线程 + 4 个文件 协同完成:

组件 所属 职责
Binlog Dump Thread 主库 将 binlog 事件推送给从库
Slave IO Thread 从库 请求并接收主库 binlog,写入 relaylog
Slave SQL Thread 从库 读取 relaylog,重放 SQL 语句
binlog 主库 记录所有数据变更事件
relaylog 从库 存储 IO 线程拉取的 binlog 副本
master.info 从库 记录连接主库的账号信息和 binlog 位置
relay-log.info 从库 记录 SQL 线程重放到的 relaylog 位置

数据流向: 主库 binlog → IO 线程拉取 → relaylog → SQL 线程重放 → 从库数据

1.2 主从构建五步流程

-- 第一步:创建复制专用用户(主库)
CREATE USER repl@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO repl@'10.0.0.%';

-- 第二步:主库全备 + 从库恢复(操作系统层面)
-- mysqldump -uroot -p123456 -A --master-data=2 --single-transaction > /tmp/full.sql
-- --single-transaction:InnoDB 表保证备份一致性(数据库中的数据 == 备份中的数据)【补】
-- scp /tmp/full.sql 10.0.0.52:/tmp/
-- mysql -uroot -p123456 < /tmp/full.sql

-- 第三步:从库配置连接主库信息
CHANGE MASTER TO
  MASTER_HOST='10.0.0.51',
  MASTER_USER='repl',
  MASTER_PASSWORD='123456',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='binlog.000008',   -- 全备文件中记录的位置点
  MASTER_LOG_POS=673,                -- 全备文件中记录的位置点
  MASTER_CONNECT_RETRY=10;

-- 第四步:启动从库同步
START SLAVE;

-- 第五步:验证主从状态
SHOW SLAVE STATUS\G
-- Slave_IO_Running:  Yes
-- Slave_SQL_Running: Yes

命令行快速监控:

mysql -uroot -p123456 -S /tmp/mysql3307.sock -e "show slave status\G" | grep "Yes"

1.3 主从故障分析

IO 线程故障(Slave_IO_Running: No):

故障原因 排查方法
网络不通 ping / telnet 检查连通性
复制用户权限/密码错误 主库重新授权验证
主库 binlog 被清理 查看主库 binlog 列表,重新全备构建
server-id 冲突 检查主从 server_id 是否唯一
防火墙拦截 检查 3306 端口是否放通

SQL 线程故障(Slave_SQL_Running: No):

故障原因 排查方法
从库已有冲突数据 查看 Relay_Master_Log_File + Exec_Master_Log_Pos 定位 binlog 事件
主从数据不一致 Last_Error 字段查看具体错误
DDL 操作冲突 主从表结构不一致导致重放失败

通用思路:SHOW SLAVE STATUS\G → 定位 Last_IO_Error / Last_SQL_Error → 按错误类型处理

1.4 延时从库

让从库落后主库一段时间,用于误操作的数据回溯恢复。

-- 从库配置延时(单位:秒)
CHANGE MASTER TO
  MASTER_DELAY = 3600;   -- 延时1小时

-- 停止 SQL 线程(保持 IO 线程继续拉取 binlog)
STOP SLAVE SQL_THREAD;

1.5 过滤复制

控制从库只同步指定的数据库,忽略其他库的变更。

需求示例: 只同步 ppt 和 word 两个数据库

永久配置(从库 my.cnf):

[mysqld]
replicate_do_db=ppt
replicate_do_db=word

临时配置(在线生效):

STOP SLAVE SQL_THREAD;
CHANGE REPLICATION FILTER REPLICATE_DO_DB = (word, ppt);
START SLAVE SQL_THREAD;

企业建议:永久和临时配置同时设置,避免重启丢失。


二、半同步复制与 GTID 扩展

2.1 半同步复制

复制模式对比:

复制模式 原理 数据安全 性能
异步复制 主库写完 binlog 立即返回 可能丢数据 最快
半同步复制 等待至少一个从库确认接收后返回 不丢数据 中等
全同步复制 所有从库确认后才返回 最安全 最差

插件安装与配置:

-- 【主库】安装半同步插件
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;

-- 【从库】安装半同步插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

-- 【从库】重启 IO 线程使插件生效
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;

-- 验证状态
-- 主库:SHOW STATUS LIKE 'rpl_semi_sync_master_status';
-- 从库:SHOW STATUS LIKE 'rpl_semi_sync_slave_status';

永久配置(my.cnf):

# ===== 主库配置 =====
rpl_semi_sync_master_enabled = ON           -- 启用半同步
rpl_semi_sync_master_timeout = 1000         -- 超时(毫秒),超时降级为异步
rpl_semi_sync_master_wait_for_slave_count = 1    -- 至少等待N个从库确认
rpl_semi_sync_master_wait_point = AFTER_SYNC     -- after_sync 模式(推荐)

# 事务组提交优化(避免 dump 线程串行提交导致延时)
binlog_group_commit_sync_delay = 1
binlog_group_commit_sync_no_delay_count = 1000

# ===== 从库配置 =====
rpl_semi_sync_slave_enabled = ON

2.2 GTID 复制

GTID(Global Transaction Identifier)全局事务标识,每个事务分配唯一 ID:

格式:source_id:transaction_id
示例:3E11FA47-71CA-11E1-9E33-C80AA9429562:23

优势: 自动识别位置点,无需手动指定日志文件和位置,便于异常恢复。

GTID 主从配置(主从 my.cnf 均需):

[mysqld]
server_id = 51                          # 每台不同
log_bin = /data/3306/data/mysql-bin
binlog_format = row
gtid-mode = on                          -- 开启 GTID
enforce-gtid-consistency = true         -- 强制 GTID 一致性
log-slave-updates = 1                   -- 从库也记录 binlog

GTID 主从构建:

-- 【主库】全备
-- mysqldump -uroot -p123456 -A --master-data=2 --single-transaction > /tmp/full.sql

-- 【主库】创建复制用户
CREATE USER repl@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO repl@'10.0.0.%';

-- 【从库】恢复全备后配置主从(核心差异:无需指定日志位置)
CHANGE MASTER TO
  MASTER_HOST = '10.0.0.51',
  MASTER_USER = 'repl',
  MASTER_PASSWORD = '123456',
  MASTER_AUTO_POSITION = 1;            -- GTID 模式,自动找位置

START SLAVE;

2.3 Clone Plugin 克隆操作

MySQL 8.0 Clone Plugin 用于高效的物理级数据拷贝。

场景 说明
本地克隆 数据备份
远程克隆 数据迁移(云主机→物理主机)

角色定义: 捐赠者(Donor)= 被克隆主机 | 接收者(Recipient)= 克隆后主机

本地克隆:

-- 安装插件
INSTALL PLUGIN clone SONAME 'mysql_clone.so';

-- 创建克隆用户
CREATE USER clone_user@'%' IDENTIFIED BY 'password';
GRANT BACKUP_ADMIN ON *.* TO 'clone_user';

-- 执行克隆(操作系统层面需先创建目录并授权)
-- mkdir -p /data/test && chown -R mysql.mysql /data/
CLONE LOCAL DATA DIRECTORY = '/data/test/clonedir';

-- 查看克隆进度
SELECT stage, state, end_time FROM performance_schema.clone_progress;

-- 启动克隆实例验证
-- mysqld_safe --datadir=/data/test/clonedir --port=3333 --socket=/tmp/mysql3333.sock --user=mysql --mysqlx=off &

远程克隆:

-- 【捐赠者】创建用户
CREATE USER test_jz@'%' IDENTIFIED BY 'password';
GRANT BACKUP_ADMIN ON *.* TO 'test_jz';

-- 【接收者】创建用户 + 设置白名单
CREATE USER test_js@'%' IDENTIFIED BY 'password';
GRANT CLONE_ADMIN ON *.* TO 'test_js';
SET GLOBAL clone_valid_donor_list = '10.0.0.51:3306';

-- 【接收者】执行远程克隆
CLONE INSTANCE FROM test_jz@'10.0.0.51':3306 IDENTIFIED BY 'password';

常见错误:

错误信息 原因
ERROR 3707: Restart server failed 克隆后接收者用户被删除,无法连接
接收用户无法登录 数据库自动反向解析导致连接失败

克隆辅助主从构建(免交互脚本):

# 【主库】安装插件+创建用户
ssh root@10.0.0.51 mysql -e \
  "INSTALL PLUGIN clone SONAME 'mysql_clone.so';
   CREATE USER test@'%' IDENTIFIED BY '123456';
   GRANT BACKUP_ADMIN ON *.* TO 'test'@'%';"

# 【从库】安装插件+设置白名单+远程克隆
mysql -e \
  "INSTALL PLUGIN clone SONAME 'mysql_clone.so';
   CREATE USER test@'%' IDENTIFIED BY '123456';
   GRANT CLONE_ADMIN ON *.* TO 'test'@'%';
   SET GLOBAL clone_valid_donor_list='10.0.0.51:3306';"

mysql -utest -p123456 -h10.0.0.52 -P3306 \
  -e "CLONE INSTANCE FROM test@'10.0.0.51':3306 IDENTIFIED BY '123456';"

# 【从库】克隆后重启并配置主从
systemctl start mysqld
mysql -uroot -p123456 -e \
  "CHANGE MASTER TO master_host='10.0.0.51',master_user='repl',
   master_password='123456',master_auto_position=1;
   START SLAVE"

# 验证(输出2行 Yes 表示正常)
mysql -uroot -p123456 -e "SHOW SLAVE STATUS\G" | grep -i "yes" | wc -l

2.4 多源复制

将多个主库的数据汇总同步到一个从库(数据中台/大数据采集场景)。

架构: Master_1(51)+ Master_2(52)→ Slave(53)

所有节点需开启 GTID,然后:

-- 【所有主库】创建复制用户(关闭 binlog 记录)
SET SQL_LOG_BIN = 0;
CREATE USER repl@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO repl@'10.0.0.%';
SET SQL_LOG_BIN = 1;

-- 【从库】通过 FOR CHANNEL 区分多个主库
CHANGE MASTER TO
  MASTER_HOST = '10.0.0.51',
  MASTER_USER = 'repl',
  MASTER_PASSWORD = '123456',
  MASTER_AUTO_POSITION = 1
  FOR CHANNEL 'Master_1';

CHANGE MASTER TO
  MASTER_HOST = '10.0.0.52',
  MASTER_USER = 'repl',
  MASTER_PASSWORD = '123456',
  MASTER_AUTO_POSITION = 1
  FOR CHANNEL 'Master_2';

START SLAVE FOR CHANNEL 'Master_1';
START SLAVE FOR CHANNEL 'Master_2';

关键语法:FOR CHANNEL '通道名',每个主库对应独立通道,可单独启停。


三、MGR 组复制

3.1 MGR 概述

MGR(MySQL Group Replication)是 MySQL 官方提供的强一致性主从复制方案。

特性 说明
一致性 基于 Paxos 协议,事务在组内所有节点提交一致
高可用 单节点故障自动剔除,服务不中断
节点要求 最少 3 台(2N+1),最多 9 台
两种模式 单主模式(默认)/ 多主模式

3.2 MGR 通用配置(所有节点 my.cnf)

[mysqld]
server_id = 51                          # 每台节点不同
log_bin = /data/3306/mysql-bin
binlog_format = row
gtid-mode = on
enforce-gtid-consistency = true
log-slave-updates = 1
skip_name_resolve
default_authentication_plugin = mysql_native_password
binlog_checksum = NONE                  # 禁用 binlog 校验(MGR 要求)
mysqlx = off

report_host = 10.0.0.51                 # 每台节点不同
report_port = 3306

# 事务依赖追踪(提升并行复制性能)
binlog_transaction_dependency_tracking = WRITESET
transaction_write_set_extraction = XXHASH64

# MGR 组配置(所有节点 group_name 必须一致)
loose-group_replication_group_name = "eb8441e9-8aef-4a86-a4bc-5beea315f04f"
loose-group_replication_start_on_boot = OFF   # 开机不自动加入
loose-group_replication_local_address = "10.0.0.51:33061"  # 每台端口不同
loose-group_replication_group_seeds = "10.0.0.51:33061,10.0.0.52:33062,10.0.0.53:33063"
loose-group_replication_bootstrap_group = OFF  # 仅引导时设 ON

# 从库额外配置
master_info_repository = TABLE
relay_log_info_repository = TABLE

3.3 单主模式构建

-- 【所有节点】安装 MGR 插件 + 设置密码
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123';
INSTALL PLUGIN group_replication SONAME 'group_replication.so';

-- 【所有节点】创建复制用户(关闭 binlog)
SET SQL_LOG_BIN = 0;
CREATE USER repl@'%' IDENTIFIED BY '123';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO repl@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN = 1;

-- 【主库 DB01】引导启动(创建 MGR 组)
CHANGE MASTER TO master_user='repl', master_password='123'
  FOR CHANNEL 'group_replication_recovery';
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;

-- 【从库 DB02/DB03】加入组
RESET MASTER;
CHANGE MASTER TO master_user='repl', master_password='123'
  FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

-- 验证组状态
SELECT * FROM performance_schema.replication_group_members;

异常重置:

STOP GROUP_REPLICATION;
RESET MASTER;
SET SQL_LOG_BIN = 0;
CHANGE MASTER TO master_user='repl', master_password='123'
  FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

3.4 多主模式构建

方式一:直接配置

# 所有节点 my.cnf 中添加
group_replication_single_primary_mode = 0     -- 关闭单主模式
group_replication_enforce_update_everywhere_checks = 1  -- 严格一致性检查

方式二:从单主切换为多主

-- 【所有节点】
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_single_primary_mode = OFF;
SET GLOBAL group_replication_enforce_update_everywhere_checks = 1;

-- 【第一个节点】引导启动
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;

-- 【其他节点】重新加入(自动成为主库)
START GROUP_REPLICATION;

-- 验证所有节点都为主库
SELECT * FROM performance_schema.replication_group_members;
模式 特点 适用场景
单主 只有1个节点可写,其他只读 默认推荐,简单稳定
多主 所有节点都可读写 高并发写入场景

四、MHA 高可用

4.1 架构概述

组件 说明
MHA Manager 管理节点,监控主库状态,负责故障检测和切换。可独立部署或部署在从库上
MHA Node 数据节点,运行在每台 MySQL 服务器上,执行数据补偿和 VIP 漂移

4.2 工作原理(7 大核心功能)

序号 功能 说明
① 监控 通过 /usr/bin/masterha_master_monitor 脚本,定时连接指定主库,识别主库运行状态 【补】
② 选主 利用 4 个数组(根据 candidate_master、check_repl_delay、log_bin、read_only 等权重)进行从库选主,选择数据最接近主库的从库成为新主 【补】
③ 数据补偿 ① 从库同步主库 binlog ② 从库彼此同步 relaylog ③ Manager 额外 binlog 补偿
④ 应用透明 VIP 漂移,对前端应用透明切换
⑤ 报警 故障切换后通知管理员(MHA 切换是一次性的)
⑥ 额外补偿 Manager 实时同步主库 binlog,从库可获取补偿
⑦ 自愈 原主修复后自动回归(仅云平台 RDS 支持)

4.3 环境准备与部署

第一步:数据库初始化 + 主从构建(参考第一章)

第二步:SSH 互信(所有节点)

rm -rf /root/.ssh && ssh-keygen
cd /root/.ssh && mv id_rsa.pub authorized_keys
scp -r /root/.ssh 10.0.0.52:/root
scp -r /root/.ssh 10.0.0.53:/root
ssh 10.0.0.51 date && ssh 10.0.0.52 date && ssh 10.0.0.53 date

第三步:MHA 软件安装

# 【所有节点】命令软链接
ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql

# 【所有节点】安装 Node
yum install perl-DBD-MySQL -y
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm

# 【Manager 节点】安装 Manager
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch \
  perl-Parallel-ForkManager perl-Time-HiRes
yum install -y mha4mysql-manager-0.58-0.el7.centos.noarch.rpm

第四步:创建 MHA 用户 + 配置文件

-- 【主库】创建 MHA 管理用户
CREATE USER mha@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY 'mha';
GRANT ALL PRIVILEGES ON *.* TO mha@'10.0.0.%';
mkdir -p /etc/mha /var/log/mha/app1
# cat > /etc/mha/app1.cnf <<EOF
[server default]
manager_log=/var/log/mha/app1/manager
manager_workdir=/var/log/mha/app1
master_binlog_dir=/data/binlog
user=mha
password=mha
ping_interval=2
repl_password=123456
repl_user=repl
ssh_user=root

[server1]
hostname=10.0.0.51
port=3306

[server2]
hostname=10.0.0.52
port=3306

[server3]
hostname=10.0.0.53
port=3306
EOF

第五步:环境检测 + 启动

masterha_check_ssh --conf=/etc/mha/app1.cnf       # 测试 SSH 互信
masterha_check_repl --conf=/etc/mha/app1.cnf       # 测试主从复制

# 启动 MHA Manager
nohup masterha_manager --conf=/etc/mha/app1.cnf \
  --remove_dead_master_conf --ignore_last_failover \
  < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

# 检查状态
masterha_check_status --conf=/etc/mha/app1.cnf
# app1 (pid:3936) is running(0:PING_OK), master:10.0.0.51

4.4 VIP 漂移配置

cd /usr/local/bin/
chmod +x /usr/local/bin/* && dos2unix /usr/local/bin/*
cp master_ip_failover master_ip_failover.bak
# 编辑 master_ip_failover 关键行
my $vip = '10.0.0.50/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";
my $ssh_Bcast_arp = "/sbin/arping -I ens33 -c 3 -A 10.0.0.50";
# MHA 配置文件加载脚本
vim /etc/mha/app1.cnf
# 添加:master_ip_failover_script=/usr/local/bin/master_ip_failover

# 手动绑定 VIP 并重启 MHA
ifconfig ens33:1 10.0.0.50/24
masterha_stop --conf=/etc/mha/app1.cnf
nohup masterha_manager --conf=/etc/mha/app1.cnf \
  --remove_dead_master_conf --ignore_last_failover \
  < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

4.5 故障切换与原主修复

自动切换流程: 监控发现异常 → 选主 → 数据补偿 → VIP 漂移 → 从库重定向 → 报警

原主修复步骤(MHA 切换是一次性的,需手动修复):

-- 1. 启动原主:systemctl start mysqld
-- 2. 恢复数据(备份或克隆)

-- 3. 重建主从关系(指向新主)
CHANGE MASTER TO
  MASTER_HOST = '10.0.0.52', MASTER_USER = 'repl',
  MASTER_PASSWORD = '123456', MASTER_AUTO_POSITION = 1;
START SLAVE;
# 4. 重新加入 MHA 集群
masterha_conf_host --command=add --conf=/etc/mha/app1.cnf \
  --hostname=10.0.0.51 --block=server1 --params="port=3306"

# 5. 恢复额外补偿
mysqlbinlog -R --host=10.0.0.52 --user=mha --password=mha \
  --raw --stop-never mysql-bin.00000X &

# 6. 重新启动 MHA
nohup masterha_manager --conf=/etc/mha/app1.cnf \
  --remove_dead_master_conf --ignore_last_failover \
  < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
masterha_check_status --conf=/etc/mha/app1.cnf

4.6 在线切换(主库非故障时主动切换)

# 配置在线切换脚本
cd /usr/local/bin/
cp master_ip_online_change master_ip_online_change.bak
# 编辑 master_ip_online_change 关键行
my $vip = "10.0.0.50";
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key $vip down";
my $ssh_Bcast_arp = "/sbin/arping -I ens33 -c 3 -A 10.0.0.50";
# 加载脚本并重启 MHA
vim /etc/mha/app1.cnf
# 添加:master_ip_online_change_script=/usr/local/bin/master_ip_online_change

masterha_stop --conf=/etc/mha/app1.cnf
nohup masterha_manager --conf=/etc/mha/app1.cnf \
  --remove_dead_master_conf --ignore_last_failover \
  < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

# 执行在线切换(主库 52 → 51)
masterha_stop --conf=/etc/mha/app1.cnf
masterha_master_switch --conf=/etc/mha/app1.cnf \
  --master_state=alive \
  --new_master_host=10.0.0.51 \
  --orig_master_is_new_slave \
  --running_updates_limit=10000
-- 在当前主库执行
FLUSH NO_WRITE_TO_BINLOG TABLES;

切换后验证: ① MHA 是否重新启动 ② VIP 是否切换到新主 ③ 主从关系是否正常


五、ProxySQL 读写分离

5.1 架构概述

端口 用途
6032 管理端口,对 ProxySQL 进行功能配置
6033 业务端口,应用程序通过此端口访问

5.2 安装

rpm -ivh proxysql-2.4.6-1-centos7.x86_64.rpm
systemctl start proxysql
netstat -lntup | grep proxy    # 确认 6032/6033 端口

5.3 配置五步走

-- 连接 ProxySQL 管理端口
mysql -uadmin -padmin -h127.0.0.1 -P6032

-- ===== 第一步:配置复制组 =====
-- 【MySQL 主库】SET GLOBAL read_only = 0;
-- 【MySQL 从库】SET GLOBAL read_only = 1;

INSERT INTO mysql_replication_hostgroups
  (writer_hostgroup, reader_hostgroup, comment)
VALUES (10, 20, 'proxy');
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL SERVERS TO RUNTIME;

-- ===== 第二步:添加 MySQL 服务器 =====
INSERT INTO mysql_servers(hostgroup_id, hostname, port)
VALUES (10, '10.0.0.50', 3306);           -- VIP 地址=写组

INSERT INTO mysql_servers(hostgroup_id, hostname, port)
VALUES (20, '10.0.0.52', 3306);           -- 从库=读组

INSERT INTO mysql_servers(hostgroup_id, hostname, port)
VALUES (20, '10.0.0.53', 3306);           -- 从库=读组
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL SERVERS TO RUNTIME;

-- ===== 第三步:配置监控 =====
-- 【MySQL 主库】
-- CREATE USER monitor@'%' IDENTIFIED WITH mysql_native_password BY '123';
-- GRANT REPLICATION CLIENT ON *.* TO monitor@'%';

SET mysql-monitor_username = 'monitor';
SET mysql-monitor_password = '123';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;

SELECT * FROM mysql_server_connect_log;          -- 连接日志
SELECT * FROM mysql_server_ping_log;              -- 心跳日志
SELECT * FROM mysql_server_replication_lag_log;   -- 延时日志

-- ===== 第四步:创建应用用户 =====
-- 【MySQL 主库】
-- CREATE USER root@'%' IDENTIFIED WITH mysql_native_password BY '123';
-- GRANT ALL ON *.* TO root@'%';

INSERT INTO mysql_users(username, password, default_hostgroup)
VALUES ('root', '123', 10);
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;

-- ===== 第五步:读写分离规则 =====
INSERT INTO mysql_query_rules
  (rule_id, active, match_pattern, destination_hostgroup, apply)
VALUES (1, 1, '^select.*for update$', 10, 1);   -- select for update → 写组

INSERT INTO mysql_query_rules
  (rule_id, active, match_pattern, destination_hostgroup, apply)
VALUES (2, 1, '^select', 20, 1);                 -- 普通 select → 读组

LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

5.4 读写分离测试

# 写操作 → 主库
mysql -uroot -p123 -P6033 -h127.0.0.1 \
  -e "begin; select @@server_id; commit"

# 读操作 → 读组轮询
mysql -uroot -p123 -P6033 -h127.0.0.1 \
  -e "select @@server_id"

ProxySQL 监控识别机制:

MySQL 状态 ProxySQL 行为
read_only = 0 划分到写组(识别失败降为读组)
read_only = 1 划分到读组(误判可能划入写组)

六、MIC 集群(MySQL InnoDB Cluster)

6.1 架构概述

MIC 是 MySQL 8.0 原生的高可用 + 读写分离方案:

组件 职责
MGR 底层主从同步(强一致性)
MySQL Shell(mysqlsh) 管理工具,创建/管理 MGR 集群
MySQL Router 路由中间件,自动读写分离

6.2 软件安装

tar xf mysql-shell-8.0.32-linux-glibc2.12-x86-64bit.tar.gz
tar xf mysql-router-8.0.32-linux-glibc2.12-x86_64.tar.xz
ln -s mysql-shell-8.0.32-linux-glibc2.12-x86-64bit mysqlsh
ln -s mysql-router-8.0.32-linux-glibc2.12-x86_64 mysql-router

# 环境变量
vim /etc/profile
# export PATH=/usr/local/mysql/bin:/usr/local/mysqlsh/bin:/usr/local/mysql-router/bin:$PATH

6.3 数据库初始化

所有节点 my.cnf 额外配置:

master_info_repository = TABLE
relay_log_info_repository = TABLE
disabled_storage_engines = MyISAM,BLACKHOLE,FEDERATED,CSV,ARCHIVE
binlog_checksum = NONE
binlog_transaction_dependency_tracking = WRITESET
transaction_write_set_extraction = XXHASH64
loose-group_replication_ip_whitelist = "master,slave01,slave02,manager"

6.4 MySQL Shell 管理 MGR 集群

-- 【所有节点】
ALTER USER root@'localhost' IDENTIFIED WITH mysql_native_password BY '123';
// 【所有节点】初始化实例配置
mysqlsh
\connect root@localhost:3306
dba.configureLocalInstance()
dba.checkInstanceConfiguration("root@localhost:3306")
// 输出 OK 表示通过

// 【主库】创建 MGR 集群
\connect root@master:3306
var cluster = dba.createCluster('xiaoQ')
// 等价于手动:change master to ... + bootstrap + start group_replication
cluster.status()

// 【从库】加入集群
var cluster = dba.getCluster('xiaoQ')
cluster.addInstance('root@slave01:3306')
cluster.addInstance('root@slave02:3306')
// 等价于手动:change master to ... + start group_replication
cluster.status()

6.5 MySQL Router 部署与读写分离

# 在 Manager 节点部署 Router
mysqlrouter --bootstrap root@master:3306 -d myrouter --user=root
cd /etc/myrouter/ && ./start.sh

# Router 端口分配:6446=读写端口 | 6447=只读端口
# 写请求 → 主库
mysql -uroot -P6446 -h10.0.0.54 -p

# 读请求 → 从库
mysql -uroot -P6447 -h10.0.0.54 -p

MIC vs 传统方案对比:

对比项 MHA + ProxySQL MIC(原生)
主从同步 异步/半同步 MGR 强一致性
高可用 MHA Manager MGR 自动选主
读写分离 ProxySQL 手动配置 Router 自动感知
运维复杂度 高(多组件独立部署) 低(Shell 一键管理)
适用版本 5.7+ 8.0+

附录:高频故障排查速查表

故障现象 排查命令/方法 常见原因
IO 线程 No SHOW SLAVE STATUS\G → Last_IO_Error 网络/权限/binlog 被清理/server_id 冲突
SQL 线程 No SHOW SLAVE STATUS\G → Last_SQL_Error 主从数据冲突/DDL 不一致
半同步降级为异步 SHOW STATUS LIKE 'rpl_semi_sync%' 从库响应超时(timeout)
MGR 无法加入组 SELECT * FROM performance_schema.replication_group_members server_id 冲突/白名单未配置/plugin 未安装
MHA 检查失败 masterha_check_repl --conf=... SSH 互信不通/复制用户权限不足
ProxySQL 全走主库 SELECT * FROM mysql_servers\G 从库 read_only 未设置/监控用户错误
Clone 远程失败 ERROR 3707 接收者用户被删除/DNS 反向解析
GTID 复制报错 SHOW SLAVE STATUS\G → Retrieved_Gtid_Set 从库非复制写入导致 GTID 冲突
posted @ 2026-03-30 23:02  gzjwo  阅读(44)  评论(0)    收藏  举报