Skip to content

MySQL Shell 管理数据库主从复制

概述

本文介绍如何使用MySQL Shell (mysqlsh) 来管理MySQL主从复制环境。MySQL Shell是官方推荐的现代化管理工具,其AdminAPI让复制管理变得简单而高效。

安装MySQL Shell

版本要求 8.0.19+

二进制下载

wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-8.0.36-linux-glibc2.17-x86-64bit.tar.gz

在Ubuntu系统上:

sudo apt install mysql-shell

在CentOS/RHEL系统上:

sudo yum install mysql-shell

mysql 配置

server-id 每个节点不同

# my.cnf
server-id = 4010
log_bin=on
enforce_gtid_consistency=on
gtid_mode=on

log_slave_updates=on

master_info_repository=table
relay_log_info_repository=table
slave_parallel_type=LOGICAL_CLOCK
slave_parallel_workers=4

clone 插件

初始化主从复制架构

启动MySQL Shell

连接到JavaScript模式:

mysqlsh

然后连接到计划做为主服务器的MySQL实例:

\connect root@master_host:3306

验证实例配置

确认要加入复制的每个实例都符合要求:

dba.checkInstanceConfiguration("root@master_host:3306");
dba.checkInstanceConfiguration("root@slave1_host:3306");
dba.checkInstanceConfiguration("root@slave2_host:3306");

配置实例

为所有实例进行基本配置:

dba.configureLocalInstance("root@master_host:3306");
dba.configureLocalInstance("root@slave1_host:3306");
dba.configureLocalInstance("root@slave2_host:3306");

创建复制集

连接到主服务器并创建副本集:

var rs = dba.createReplicaSet("production_rs");

确认副本集创建完成:

rs.status();

添加从节点

将从服务器加入到复制集中:

// 添加第一个从节点
rs.addInstance("root@slave1_host:3306", {
  recoveryMethod: "clone",
});

// 添加第二个从节点
rs.addInstance("root@slave2_host:3306", {
  recoveryMethod: "clone",
});

查看完整的复制集状态:

rs.status();

配置 MySQL Router 路由

初始化Router配置

MySQL Router提供连接路由功能,可根据读写类型自动转发请求到合适的MySQL实例。

首先使用管理员账户连接到当前主节点初始化Router配置:

mysqlrouter --bootstrap root@master_host:3306 --user=mysqlrouter

按提示输入主节点的数据库管理员密码。该命令会在MySQL主节点上创建必要账户,并自动生成配置文件。

启动Router服务

使用以下任一命令启动服务:

# systemd方式(推荐)
sudo systemctl start mysqlrouter

# 传统服务方式
sudo /etc/init.d/mysqlrouter restart

# 或者直接运行
mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf

Router启动后,会监听以下端口:

  • 6446/64460: 写入端口,所有写操作路由到主节点
  • 6447/64470: 读取端口,读操作分散到各个从节点

验证Router路由

通过MySQL Shell连接不同端口验证路由器的负载均衡功能:

// 连接到写入端口,确保请求被路由到主节点
var writeSession = mysql.getSession({
  host: "routerip_host",
  port: 6446,
  user: "user",
  password: "password",
});
writeSession.runSql("SELECT @@hostname, @@port, @@read_only");

// 连接到读取端口,请求被路由到一个从节点
var readSession = mysql.getSession({
  host: "routerip_host",
  port: 6447,
  user: "user",
  password: "password",
});
readSession.runSql("SELECT @@hostname, @@port, @@read_only");
// 连接到其中一个节点检查Router状态
\connect root@master_host:3306
var rs = dba.getReplicaSet();
rs.listRouters();

通过这种方式,应用只需要连接固定的Router端口(6446用于写入,6447用于读取),Router会自动将请求路由到合适的数据库节点。

管理操作

查看从节点状态

var replicaset = dba.getReplicaSet();
replicaset.status();

切换主节点

在维护期间切换主节点:

rs.setPrimaryInstance("root@slave1_host:3306");

故障处理

恢复故障节点

重新加入失败的从节点:

rs.rejoinInstance("root@slave1_host:3306");

若上述操作失败,需要重新添加节点:

rs.removeInstance("root@slave1_host:3306");
rs.addInstance("root@slave1_host:3306", {
  recoveryMethod: "clone",
});

常用命令总结

// 获取当前复制集引用
var rs = dba.getReplicaSet();

// 查看状态
rs.status();
rs.status({ extended: 1 }); // 详细状态

// 添加节点
rs.addInstance("user@host:port", { recoveryMethod: "clone" });

// 移除节点
rs.removeInstance("user@host:port");

// 设置主节点
rs.setPrimaryInstance("user@host:port");

// 强制重连故障节点
rs.rejoinInstance("user@host:port");

故障排除

常见问题1:网络不通导致连接失败

  • 检查防火墙配置,确保3306等必要端口开放
  • 验证各实例的 bind-address 配置允许外部连接

常见问题2:克隆失败

  • 确认克隆源和目标有足够的磁盘空间
  • 检查网络带宽和稳定性

常见问题3:权限不足

  • 验证用户具有REPLICATION CLIENT, REPLICATION SLAVE权限
  • 检查克隆PLUGIN (CLONE_ADMIN) 权限