文章目录
一、MySQL安装(8.0.27)
1.二进制安装
# 临时关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 临时关闭SELinux
setenforce 0
# 永久关闭SELinux(需重启生效)
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
#安装相关包
yum -y install libaio numactl-libs ncurses-compat-libs tar wget
#用户和组
groupadd mysql
useradd -r -s /sbin/nologin -g mysql mysql
#准备程序文件
wget https://mirrors.aliyun.com/mysql/MySQL-8.0/mysql-8.0.27-linux-glibc2.12-x86_64.tar.xz
tar -xvf mysql-8.0.27-linux-glibc2.12-x86_64.tar.xz -C /usr/local
cd /usr/local
ln -s mysql-8.0.27-linux-glibc2.12-x86_64/ mysql
chown -R root.root /usr/local/mysql
#准备环境变量
echo 'PATH=/usr/local/mysql/bin:$PATH' > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
#准备配置文件
vim /etc/my.cnf
[mysqld]
[mysqld]
log-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
socket=/data/mysql/mysql.sock
default-character-set = utf8mb4
#修改配置文件权限
chown mysql:mysql /etc/my.cnf
chmod 644 /etc/my.cnf
#初始化数据库文件并提取root密码 (在/data/mysql 会自动生成,但是/data/必须事先存在)
生成随机密码:
mysqld --initialize --user=mysql --datadir=/data/mysql
awk '/temporary password/{print $NF}' /data/mysql/mysql.log
LufavlMka6,!
#创建system启动服务
vim /usr/lib/systemd/system/mysqld.service
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
Type=notify
TimeoutSec=0
PermissionsStartOnly=true
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf $MYSQLD_OPTS
LimitNOFILE = 5000
Restart=on-failure
RestartPreventExitStatus=1
Environment=MYSQLD_PARENT_PID=1
PrivateTmp=false
# 重新加载systemd配置
systemctl daemon-reload
systemctl start mysqld
systemctl enable mysqld
# 查看服务状态(显示active(running)即启动成功)
systemctl status mysqld
#登录 MySQL(使用第一步获取的临时密码)
mysql -uroot -p'LufavlMka6,!'
#修改MySQL密码
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'root@123456';
二、MySQL集群Cluster
1.主从复制
| Cluster Role |
System |
IP |
Hostname |
| Master |
Rocky8.10 |
1010.0.0.8 |
MySQL-master |
| Slave |
Rocky8.10 |
10.0.0.18 |
MySQL-slave01 |
| Slave |
Rocky8.10 |
10.0.0.28 |
MySQL-slave02 |
(1)主节点配置
#配置文件
[root@MySQL-master ~]# vim /etc/my.cnf
[mysqld]
server-id=1 #唯一标识ID,非零的整数;区分主从节点;开启log-bin的必要条件,
log-bin=/data/mysql/logbin/mysql-bin #开启并制定binlog日志路径
read_only=off
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
port=3306
user=root #测试环境,用户名、密码写入配置文件方便测试
password=root@123456
socket=/data/mysql/mysql.sock
default-character-set=utf8mb4
[client]
socket=/data/mysql/mysql.sock
#创建logbin目录
[root@MySQL-master ~]# mkdir -p /data/mysql/logbin
[root@MySQL-master ~]# chown -R mysql.mysql /data/mysql/logbin
#重启生效
[root@MySQL-master ~]# systemctl deamon-relod
[root@MySQL-master ~]# systemctl restart mysqld
#创建从节点连接的用户,并授予权限
[root@MySQL-master ~]#mysql
mysql> create user repluser@"10.0.0.%" identified by "123456";
Query OK, 0 rows affected (0.01 sec) #创建远程连接用户名密码
mysql> ALTER USER 'repluser'@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.03 sec) #MySQL8.0版本必须要使用mysql_native_password密码插件
mysql> grant replication slave on *.* to repluser@"10.0.0.%";
Query OK, 0 rows affected (0.01 sec) #用户权限限制
mysql> FLUSH PRIVILEGES; #刷新权限配置
Query OK, 0 rows affected (0.01 sec)
mysql> show master status; #查看最新log-bin日志位置
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 157 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
#完全备份
[root@MySQL-master ~]# mysqldump -u -proot@123456 -A -F --master-data=1 --single-transaction > /data/all.sql #生产中输入密码一定要使用交互式
#将完全备份拷贝到从节点
[root@MySQL-master ~]# scp /data/all.sql 10.0.0.18:/data
[root@MySQL-master ~]# scp /data/all.sql 10.0.0.28:/data
(2)从节点配置(以MySQL-slave01为例)
#配置文件
[root@MySQL-slave01 ~]# vim /etc/my.cnf
[mysqld]
server-id = 2
read_only = on #从节点开启只读模式,只能查询
log-bin=/data/mysql/logbin/mysql-bin #log-bin 从节点一般不开启;关闭 =off即可
relay_log=/data/mysql/relay-log/relay-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
user=root
password=root@123456
socket=/data/mysql/mysql.sock
default-character-set=utf8mb4
[client]
socket=/data/mysql/mysql.sock
#创建logbin目录
[root@MySQL-slave01 ~]# mkdir -p /data/mysql/logbin
[root@MySQL-slave01 ~]# chown -R mysql.mysql /data/mysql/logbin
[root@MySQL-slave01 ~]# mkdir -p /data/mysql/relay-log
[root@MySQL-slave01 ~]# chown -R mysql.mysql /data/mysql/relay-log
#重启生效
[root@MySQL-slave01 ~]# systemctl deamon-relod
[root@MySQL-slave01 ~]# systemctl restart mysqld
#设置同步规则
[root@MySQL-slave01 ~]# vim /data/all.sql
-- Position to start replication or point-in-time recovery from
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=157;
--
-- Current Database: `mysql`
#导入规则并启动
[root@MySQL-slave01 ~]# mysql
mysql> set sql_log_bin=0; #临时关闭log-bin日志
Query OK, 0 rows affected (0.00 sec)
mysql> source /data/all.sql #读取指定路径的 SQL 文件,并逐行执行文件中的所有 SQL 语句。
mysql> set sql_log_bin=1; #开启log-bin日志
Query OK, 0 rows affected (0.00 sec)
mysql> start slave; #启动复制进程,若之前就是从库source之前需要stop slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show slave status\G #查看Slave_IO_Running 和 Slave_SQL_Running 是否为 Yes,确认配置生效。
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.8
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 157
Relay_Log_File: rocky8-relay-bin.000002
Relay_Log_Pos: 1174
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes #IO和SQL线程全是yes
Slave_SQL_Running: Yes
...省略...
1 row in set, 1 warning (0.00 sec)
#在主节点查看从节点
[root@MySQL-master ~]# mysql
mysql> SHOW SLAVE HOSTS;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 2 | | 3306 | 1 | 4eff1fe4-f1e8-11f0-a914-000c295a819b |
+-----------+------+------+-----------+--------------------------------------+
(3)测试是否同步
#测试sql脚本,批量生成数据
[root@MySQL-master ~]# vim /data/testlog.sql
create table testlog (id int auto_increment primary key,name char(10),salary int default 20);
delimiter $$
create procedure sp_testlog()
begin
declare i int;
set i = 1;
while i <= 100000
do insert into testlog(name,salary) values (concat('wang',FLOOR(RAND() * 100000)),FLOOR(RAND() * 1000000));
set i = i +1;
end while;
end$$
delimiter ;
#执行脚本
[root@MySQL-master ~]# mysql
mysql> source /data/testlog.sql; #执行脚本,创建存储过程sp_testlog()
Query OK, 0 rows affected (0.04 sec)
mysql> call sp_testlog(); #调用存储过程sp_testlog(),执行插入10万条数据的逻辑
Query OK, 1 row affected (3 min 47.46 sec)
mysql> SELECT COUNT(*) FROM test.testlog;
+----------+
| COUNT(*) |
+----------+
| 100000 |
+----------+
1 row in set (0.02 sec)
#同时观察Slave01、Slave02节点同步情况
[root@MySQL-slave01 ~]# mysql
mysql> SELECT COUNT(*) FROM test.testlog;
+----------+
| COUNT(*) |
+----------+
| 60036 |
+----------+
1 row in set (0.01 sec)
[root@MySQL-slave02 ~]# mysql
mysql> SELECT COUNT(*) FROM test.testlog;
+----------+
| COUNT(*) |
+----------+
| 56204 |
+----------+
1 row in set (0.39 sec)
(4)实例:当master服务器宕机,提升一个slave成为新的master
#解析最新时间的中继日志看是否有没执行完的SQL语句,若有手动执行SQL语句,确保数据完整 (这种情况是在中继日志完全同步了主节点的log_bin)
[root@MySQL-slave01 ~]# mysqlbinlog /data/mysql/relay-log/relay-bin.000025 | tail -500
#修改配置文件
[root@MySQL-slave01 ~]# vim /etc/my.cnf
[mysqld]
server-id = 2
read_only = off #关闭只读
log-bin=/data/mysql/logbin/mysql-bin #开启log-bin日志
relay_log=/data/mysql/relay-log/relay-bin
datadir = /data/mysql
socket = /data/mysql/mysql.sock
log-error = /data/mysql/mysql.log
pid-file = /data/mysql/mysql.pid
default_storage_engine = InnoDB
character_set_server = utf8mb4
[mysql]
user=root
password=root@123456
socket = /data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
#清除旧的master复制信息
[root@MySQL-slave01 ~]# mysql
mysql> show variables like 'read_only';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only | ON |
+---------------+-------+
1 row in set (0.70 sec)
mysql> set global read_only=off; #临时生效,手动关闭只读模式read_only
Query OK, 0 rows affected (0.02 sec)
mysql> show variables like 'log_bin'; #确认log_bin是否已经打开,ON 开启、OFF 关闭
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.01 sec)
mysql> stop slave; #停止slave复制线程
Query OK, 0 rows affected, 1 warning (0.70 sec)
mysql> reset slave all; #刷新slave
Query OK, 0 rows affected, 1 warning (0.14 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 | 156 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.04 sec)
#在新的master上完全备份
[root@MySQL-slave01 ~]# mysqldump -uroot -p -A -F --single-transaction --source-data=1 > /data/all.sql
Enter password:
[root@MySQL-slave01 ~]# ls /data/
all.sql mysql
[root@MySQL-slave01 ~]# scp /data/all.sql 10.0.0.28:/data
all.sql 100% 3793KB 31.0MB/s 00:00
#其他的slave重新还原数据库,指向新的master
[root@MySQL-slave02 ~]# vim /data/all.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.18',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT='3306',
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=156;
#同步数据
[root@MySQL-slave02 ~]# mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.01 sec)
mysql> source /data/all.sql;
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.28
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 156
Relay_Log_File: rocky8-relay-bin.000002
Relay_Log_Pos: 326
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...省略...
2.级联复制
| Cluster Role |
System |
IP |
Hostname |
| Master |
Rocky8.10 |
1010.0.0.8 |
MySQL-master |
| 级联Slave |
Rocky8.10 |
10.0.0.18 |
MySQL-slave01 |
| Slave |
Rocky8.10 |
10.0.0.28 |
MySQL-slave02 |
(1)主节点配置
#修改配置文件
[root@MySQL-master ~]# vim /etc/my.cnf
[mysqld]
server-id=1
log-bin=/data/mysql/logbin/mysql-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
user=root
password=root@123456
socket=/data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
#创建log-bin存放目录
[root@MySQL-master ~]# mkdir -p /data/mysql/logbin
[root@MySQL-master ~]# chown -R mysql.mysql /data/mysql/logbin
#重启生效
[root@MySQL-master ~]# systemctl daemon-reload
[root@MySQL-master ~]# systemctl restart mysqld
[root@MySQL-master ~]# systemctl status mysqld
#创建远程连接用户
[root@MySQL-master ~]# mysql
mysql> create user repluser@"10.0.0.%" identified by "123456";
Query OK, 0 rows affected (2.54 sec)
mysql> ALTER USER 'repluser'@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.12 sec)
mysql> grant replication slave on *.* to repluser@"10.0.0.%";
Query OK, 0 rows affected (0.08 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 | 1003 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.04 sec)
#完全备份并同步到节点slave01、slave02
[root@MySQL-master ~]# mysqldump -uroot -p -A -F --source-data=1 --single-transaction > /data/all.sql
[root@MySQL-master ~]# scp /data/all.sql 10.0.0.18:/data
[root@MySQL-master ~]# scp /data/all.sql 10.0.0.28:/data
(2)级联节点配置
#修改配置文件
[root@MySQL-slave01 ~]# vim /etc/my.cnf
[mysqld]
server-id=2
read-only = on #开启只读模式
log-bin = /data/mysql/logbin/mysql-bin #必须开启log-bin日志
log_slave_updates = on #让从库把从主库同步过来的事务,也写入自己的 binlog 日志中
relay_log = /data/mysql/relay-log/relay-bin
datadir = /data/mysql
socket = /data/mysql/mysql.sock
log-error = /data/mysql/mysql.log
pid-file = /data/mysql/mysql.pid
default_storage_engine = InnoDB
character_set_server = utf8mb4
[mysql]
user=root
password = root@123456
socket = /data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket = /data/mysql/mysql.sock
#创建目录并授予权限
[root@MySQL-slave01 ~]# mkdir -p /data/mysql/logbin
[root@MySQL-slave01 ~]# chown -R mysql.mysql /data/mysql/logbin
[root@MySQL-slave01 ~]# mkdir -p /data/mysql/relay-log
[root@MySQL-slave01 ~]# chown -R mysql.mysql /data/mysql/relay-log
#重启生效
[root@MySQL-slave01 ~]# systemctl daemon-reload
[root@MySQL-slave01 ~]# systemctl restart mysqld
#同步数据
root@MySQL-slave01 ~]# vim /data/all.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS= 1003;
[root@MySQL-slave01 ~]# mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /data/all.sql
Query OK, 0 rows affected (0.00 sec)
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.09 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.8
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 1003
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
mysql> show master logs;
+------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 | 179 | No |
| mysql-bin.000002 | 156 | No |
+------------------+-----------+-----------+
2 rows in set (0.00 sec)
#在级联节点slave01刷新一下用户权限
mysql> SELECT user, host FROM user WHERE user = 'repluser';
+----------+----------+
| user | host |
+----------+----------+
| repluser | 10.0.0.% |
+----------+----------+
1 row in set (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.08 sec)
mysql> SHOW GRANTS FOR 'repluser'@'10.0.0.%';
+---------------------------------------------------------+
| Grants for repluser@10.0.0.% |
+---------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO `repluser`@`10.0.0.%` |
+---------------------------------------------------------+
1 row in set (0.03 sec)
(3)从节点配置
#修改配置文件
[root@MySQL-slave02 ~]# more /etc/my.cnf
[mysqld]
server-id = 3
read-only = on #开启只读模式
relay_log = /data/mysql/relay-log/relay-bin #中继 日志路径
log-bin = /data/mysql/logbin/mysql-bin #可以关闭/也可以开启
datadir = /data/mysql
socket = /data/mysql/mysql.sock
log-error = /data/mysql/mysql.log
pid-file = /data/mysql/mysql.pid
default_storage_engine = InnoDB
character_set_server = utf8mb4
[mysql]
user = root
password = root@123456
socket = /data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket = /data/mysql/mysql.sock
#创建目录并授予权限
[root@MySQL-slave02 ~]# mkdir -p /data/mysql/logbin
[root@MySQL-slave02 ~]# chown -R mysql.mysql /data/mysql/logbin
[root@MySQL-slave02 ~]# mkdir -p /data/mysql/relay-log
[root@MySQL-slave02 ~]# chown -R mysql.mysql /data/mysql/relay-log
#重启生效
[root@MySQL-slave02 ~]# systemctl daemon-reload
[root@MySQL-slave02 ~]# systemctl restart mysql
#同步数据
[root@MySQL-slave02 ~]# vim /data/all.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.38',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000002',
MASTER_LOG_POS=156;
[root@MySQL-slave02 ~]# mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /data/all.sql;
Query OK, 0 rows affected (0.00 sec)
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.04 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.18
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 156
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 496
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#在主节点查看级联节点信息
[root@MySQL-master ~]# mysql
mysql> SHOW SLAVE HOSTS;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 2 | | 3306 | 1 | 4eff1fe4-f1e8-11f0-a914-000c295a819b |
+-----------+------+------+-----------+--------------------------------------+
#在级联节点查看从节点信息
[root@MySQL-slave01 ~]# mysql
mysql> SHOW SLAVE HOSTS;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 3 | | 3306 | 2 | 6ab6b4a8-f274-11f0-b756-000c29a62e45 |
+-----------+------+------+-----------+--------------------------------------+
3.主主复制
| Cluster Role |
System |
IP |
Hostname |
| Master |
Rocky8.10 |
1010.0.0.8 |
MySQL-master01 |
| Master |
Rocky8.10 |
10.0.0.18 |
MySQL-master02 |
(1)主节点master01配置
#修改配置文件
[root@MySQL-master01 ~]# vim /etc/my.cnf
[mysqld]
server-id=1
log-bin=/data/mysql/logbin/mysql-bin
relay_log = /data/mysql/relay-log/relay-bin
auto_increment_offset=1 #自增列的步长 offset的值必须 ≤ increment的值,否则会报错
auto_increment_increment=2 ##自增列的起始偏移量 避免双节点自增 ID 冲突
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
user=root
password=root@123456
socket=/data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
#创建目录并授予权限
[root@MySQL-master01 ~]# mkdir -p /data/mysql/logbin
[root@MySQL-master01 ~]# chown -R mysql.mysql /data/mysql/logbin
[root@MySQL-master01 ~]# mkdir -p /data/mysql/relay-log
[root@MySQL-master01 ~]# chown -R mysql.mysql /data/mysql/relay-log
#重启生效
[root@MySQL-master01 ~]# systemctl daemon-reload
[root@MySQL-master01 ~]# systemctl restart mysqld
#创建连接用户并授予权限
[root@MySQL-master01 ~]# mysql
mysql> create user repluser@"10.0.0.%" identified by "123456";
Query OK, 0 rows affected (0.27 sec)
mysql> ALTER USER 'repluser'@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.04 sec)
mysql> grant replication slave on *.* to repluser@"10.0.0.%";
Query OK, 0 rows affected (0.04 sec)
mysql> show master logs;
+------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 | 203 | No |
| mysql-bin.000002 | 179 | No |
| mysql-bin.000003 | 156 | No |
+------------------+-----------+-----------+
3 rows in set (0.00 sec)
#完全备份
[root@MySQL-master01 ~]# mysqldump -uroot -p -A -F --source-data=1 --single-transaction > /data/all01.sql
[root@MySQL-master01 ~]# scp /data/all01.sql 10.0.0.18:/data
(2)主节点master02配置
[root@MySQL-master02 ~]# vim /etc/my.cnf
[mysqld]
server-id=2
log-bin = /data/mysql/logbin/mysql-bin
relay_log = /data/mysql/relay-log/relay-bin
auto_increment_offset=1 #自增列的步长
auto_increment_increment=2 #自增列的起始偏移量
datadir = /data/mysql
socket = /data/mysql/mysql.sock
log-error = /data/mysql/mysql.log
pid-file = /data/mysql/mysql.pid
default_storage_engine = InnoDB
character_set_server = utf8mb4
[mysql]
user=root
password=root@123456
socket = /data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
character_set_client = utf8mb4
#创建目录并授予权限
[root@MySQL-master02 ~]# mkdir -p /data/mysql/logbin
[root@MySQL-master02 ~]# chown -R mysql.mysql /data/mysql/logbin
[root@MySQL-master02 ~]# mkdir -p /data/mysql/relay-log
[root@MySQL-master02 ~]# chown -R mysql.mysql /data/mysql/relay-log
#重启并生效
[root@MySQL-master02 ~]# systemctl daemon-reload
[root@MySQL-master02 ~]# systemctl restart mysqld
#同步数据
[root@MySQL-master02 ~]# mysql
mysql> show master logs;
+------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000001 | 179 | No |
| mysql-bin.000002 | 203 | No |
| mysql-bin.000003 | 156 | No |
+------------------+-----------+-----------+
#完全备份
[root@MySQL-master02 ~]# mysqldump -uroot -p -A -F --source-data=1 --single-transaction > /data/all02.sql
[root@MySQL-master02 ~]# scp /data/all02.sql 10.0.0.8:/data
(3)同步master01和master02
#先在master02上同步数据
[root@MySQL-master02 ~]# vim /data/all01.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.18',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=156;
[root@MySQL-master02 ~]# mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /data/all.sql;
Query OK, 0 rows affected (0.00 sec)
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.04 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.8
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 156
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#刷新权限
[root@MySQL-master02 ~]# mysql
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.07 sec)
#再在master01上同步数据
[root@MySQL-master01 ~]# vim /data/all01.sql
CHANGE MASTER TO
MASTER_HOST='10.0.0.8',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=156;
[root@MySQL-master01 ~]# mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /data/all.sql;
Query OK, 0 rows affected (0.00 sec)
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.04 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.18
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 333
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 501
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
(4)测试是否互为主备
#在master01上创建db1库,表t1
[root@MySQL-master01 ~]# mysql
mysql> create database db1;
Query OK, 1 row affected (0.16 sec)
mysql> use db1;
Database changed
mysql> create table t1(id int auto_increment primary key,name char(10));
Query OK, 0 rows affected (0.22 sec)
#在master02查看数据是否同步
[root@MySQL-master02 ~]# mysql
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.05 sec)
mysql> use db1;
Database changed
mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| t1 |
+---------------+
1 row in set (0.03 sec)
##在master02上创建db2库,表t2
[root@MySQL-master02 ~]# mysql
mysql> create database db2;
Query OK, 1 row affected (0.02 sec)
mysql> use db2;
Database changed
mysql> create table t2(id int auto_increment primary key,name char(10));
Query OK, 0 rows affected (0.06 sec)
#在master01上查看数据是否同步]
[root@MySQL-master01 ~]# mysql
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| db2 |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
mysql> use db2;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
mysql> show tables;
+---------------+
| Tables_in_db2 |
+---------------+
| t2 |
+---------------+
1 row in set (0.00 sec)
(5)实例:两个节点同时创建数据库,发生复制冲突,不再同步
#两个节点同时插入数据 (禁止同时在两个节点同时插入数据,相同数据时不会出现问题,一旦数据不同)
mysql> insert t1(id,name) values(3,'yue');
Query OK, 1 row affected (0.92 sec)
mysql> select * from t1;
+----+------+
| id | name |
+----+------+
| 1 | bai |
| 2 | fu |
| 3 | yue |
+----+------+
3 rows in set (0.00 sec)
#两个节点同时创建数据库,发生复制冲突,不再同步
mysql> create database db3;
Query OK, 1 row affected (0.44 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.18
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1660
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 920
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1062
Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction 'ANONYMOUS' at master log mysql-bin.000004, end_log_pos 1442. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.
#修复冲突(不建议使用,主主同步 也要使用主从模式)
#两个节点同时停止服务
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.08 sec)
mysql> set global sql_slave_skip_counter = 3; #强制跳过冲突的事务恢复同步状态,但是会造成数据不同步
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.66 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.18
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1660
Relay_Log_File: relay-bin.000004
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
4.半同步复制
| Cluster Role |
System |
IP |
Hostname |
| Master |
Rocky8.10 |
1010.0.0.8 |
MySQL-master |
| Slave |
Rocky8.10 |
10.0.0.18 |
MySQL-slave01 |
| Slave |
Rocky8.10 |
10.0.0.28 |
MySQL-slave02 |
(1)主节点配置(在主从复制的基础上)
#安装半同步复制主库插件
[root@MySQL-master ~]# mysql
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected, 1 warning (1.70 sec)
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
1 row in set (0.00 sec)
#修改配置文件
[root@MySQL-master ~]# vim /etc/my.cnf
[mysqld]
server-id=1
log-bin=/data/mysql/logbin/mysql-bin
plugin-load-add=rpl_semi_sync_master.so #加载半同步复制主库插件
rpl_semi_sync_master_enabled #启用半同步复制
rpl_semi_sync_master_timeout=3000 #主库等待从库确认的超时时间
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
user=root
password=root@123456
socket=/data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
#重启生效
[root@MySQL-master ~]# systemctl restart mysqld
(2)从节点配置(slave01、slave02)
#安装半同步复制从库插件
[root@MySQL-slave01 ~]# mysql
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected, 1 warning (0.76 sec)
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+---------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE |
+---------------------+---------------+
1 row in set (0.01 sec)
#修改配置文件
[root@MySQL-slave01 ~]# vim /etc/my.cnf
[mysqld]
server-id=3
read-only = on
plugin-load-add=rpl_semi_sync_master.so #加载半同步复制从库插件
rpl_semi_sync_slave_enabled = on #启用半同步复制
log-bin=/data/mysql/logbin/mysql-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
user=root
password=root@123456
socket=/data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
#重启生效
[root@MySQL-slave01 ~]# systemctl restart mysqld
(3)主节点状态验证
[root@MySQL-master ~]# mysql
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 4 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
+--------------------------------------------+-------+
14 rows in set (0.04 sec)
三、MySQL中间件代理服务
1.MyCat
| Cluster Role |
System |
IP |
Hostname |
| Client |
Rocky8.10 |
1010.0.0.10 |
Client |
| Mycat |
Rocky8.10 |
1010.0.0.100 |
Mycat |
| Master |
Rocky8.10 |
1010.0.0.8 |
MySQL-master |
| Slave |
Rocky8.10 |
10.0.0.18 |
MySQL-slave01 |
| Slave |
Rocky8.10 |
10.0.0.28 |
MySQL-slave02 |
(1)主节点配置(在主从同步的基础上)
#创建一个给mycat的用户(会同步给从节点)
[root@MySQL-master ~]# mysql
mysql> create user 'bai'@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (2.72 sec)
mysql> ALTER USER 'bai'@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.14 sec)
mysql> grant all on mycat.* to 'bai'@'10.0.0.%';
Query OK, 0 rows affected (0.31 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.12 sec)
#创建一个mycat数据库和表t1
mysql> CREATE DATABASE IF NOT EXISTS mycat;
Query OK, 1 row affected (0.14 sec)
mysql> USE mycat;
Database changed
mysql> CREATE TABLE IF NOT EXISTS t1 (
-> id INT AUTO_INCREMENT PRIMARY KEY,
-> name VARCHAR(20) NOT NULL
-> );
Query OK, 0 rows affected (0.71 sec)
mysql> INSERT INTO t1 (name) VALUES ('yue');
Query OK, 1 row affected (0.24 sec)
#若是自定义的mysql.log路径,需要开启通用查询日志(主节点和从节点都需要开启)
[root@MySQL-master ~]# mysql
mysql> SET GLOBAL general_log = ON;
Query OK, 0 rows affected (0.33 sec)
mysql> SHOW VARIABLES LIKE 'general_log_file';
+------------------+------------------------------+
| Variable_name | Value |
+------------------+------------------------------+
| general_log_file | /data/mysql/MySQL-master.log |
+------------------+------------------------------+
1 row in set (0.29 sec)
[root@MySQL-slave01 ~]# mysql
mysql> SET GLOBAL general_log = ON;
Query OK, 0 rows affected (0.07 sec)
mysql> SHOW VARIABLES LIKE 'general_log_file';
\+------------------+-------------------------------+
| Variable_name | Value |
+------------------+-------------------------------+
| general_log_file | /data/mysql/MySQL-slave01.log |
+------------------+-------------------------------+
1 row in set (0.35 sec)
[root@MySQL-slave02 ~]# mysql
mysql> SET GLOBAL general_log = ON;
Query OK, 0 rows affected (0.07 sec)
mysql> SHOW VARIABLES LIKE 'general_log_file';
\+------------------+-------------------------------+
| Variable_name | Value |
+------------------+-------------------------------+
| general_log_file | /data/mysql/MySQL-slave02.log |
+------------------+-------------------------------+
1 row in set (0.35 sec)
(2)配置Mycat服务器
##安装Mycat-1.6.7.6
[root@Mycat ~]# yum -y install java
[root@Mycat ~]# wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz
[root@Mycat ~]# mkdir /apps
[root@Mycat ~]# tar xvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /apps
[root@Mycat ~]# chmod -R 755 /apps/mycat/
[root@Mycat ~]# chown -R root:root /apps/mycat/
#配置环境变量
[root@Mycat ~]# echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh
[root@Mycat ~]# . /etc/profile.d/mycat.sh
[root@Mycat ~]# echo $PATH
/apps/mycat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
#启动Mycat
[root@Mycat ~]# mycat strat
#修改配置文件(可以修改Mycat的端口号和默认用户名,密码)
[root@Mycat ~]# vim /apps/mycat/conf/server.xml
...省略...
<property name="serverPort">3306</property>
...省略...
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="defaultSchema">TESTDB</property>
[root@Mycat ~]# vim /apps/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="mycat" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select 1</heartbeat>
<writeHost host="host1" url="10.0.0.8:3306" user="bai" password="123456">
<readHost host="host2" url="10.0.0.18:3306" user="bai" password="123456" />
<readHost host="host3" url="10.0.0.28:3306" user="bai" password="123456" />
</writeHost>
</dataHost>
</mycat:schema>
#重新启动mycat
[root@Mycat ~]# mycat stop
Stopping Mycat-server...
Mycat-server was not running.
[root@Mycat ~]# mycat start
Starting Mycat-server...
[root@Mycat ~]# tail -f /apps/mycat/logs/wrapper.log
INFO | jvm 1 | 2026/01/27 15:02:13 | at io.mycat.config.MycatConfig.<init>(MycatConfig.java:72)
INFO | jvm 1 | 2026/01/27 15:02:13 | at io.mycat.MycatServer.<init>(MycatServer.java:180)
INFO | jvm 1 | 2026/01/27 15:02:13 | at io.mycat.MycatServer.<clinit>(MycatServer.java:121)
INFO | jvm 1 | 2026/01/27 15:02:13 | ... 7 more
STATUS | wrapper | 2026/01/27 15:02:15 | <-- Wrapper Stopped
STATUS | wrapper | 2026/01/27 15:02:51 | --> Wrapper Started as Daemon
STATUS | wrapper | 2026/01/27 15:02:52 | Launching a JVM...
INFO | jvm 1 | 2026/01/27 15:02:52 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO | jvm 1 | 2026/01/27 15:02:52 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
INFO | jvm 1 | 2026/01/27 15:02:52 |
INFO | jvm 1 | 2026/01/27 15:02:55 | MyCAT Server startup successfully. see logs in logs/mycat.log
(3)在客户端测试
#需要安装mysql客户端
[root@Client ~]# mysql -uroot -p123456 -h 10.0.0.100 -P 3306
mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB |
+----------+
1 row in set (0.00 sec)
mysql> use TESTDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-----------------+
| Tables_in_mycat |
+-----------------+
| t1 |
+-----------------+
1 row in set (0.01 sec)
mysql> select * from t1;
+----+-------------+
| id | name |
+----+-------------+
| 1 | yue |
| 2 | mycat_test |
| 3 | mycat_test2 |
| 4 | mycat_test3 |
| 5 | mycat_test4 |
+----+-------------+
5 rows in set (0.01 sec)
mysql> insert into t1 (name) values ('mycat_test5');
Query OK, 1 row affected (0.39 sec)
(4)监控主机点和从节点
#主节点
[root@MySQL-master ~]# tail -f /data/mysql/MySQL-master.log
2026-01-27T07:18:55.157042Z 56 Query select 1
2026-01-27T07:19:05.156943Z 60 Query select 1
2026-01-27T07:19:15.156810Z 62 Query select 1
2026-01-27T07:19:25.157044Z 57 Query select 1
2026-01-27T07:19:35.157643Z 61 Query select 1
2026-01-27T07:19:43.810670Z 54 Field List t1
2026-01-27T07:19:45.157019Z 58 Query select 1
2026-01-27T07:19:55.157649Z 55 Query select 1
2026-01-27T07:20:04.170055Z 42 Quit
2026-01-27T07:20:05.157508Z 53 Query select 1
2026-01-27T07:20:15.157925Z 59 Query select 1
2026-01-27T07:20:25.158238Z 56 Query select 1
2026-01-27T07:20:35.157211Z 60 Query select 1
2026-01-27T07:20:39.608703Z 62 Query insert into t1 (name) values ('mycat_test5')
2026-01-27T07:20:45.158084Z 57 Query select 1
#从节点
[root@MySQL-slave01 ~]# tail -f /data/mysql/MySQL-slave01.log
2026-01-27T07:18:55.174435Z 40 Query select 1
2026-01-27T07:19:05.175096Z 41 Query select 1
2026-01-27T07:19:15.201230Z 46 Query select 1
2026-01-27T07:19:25.174058Z 43 Query select 1
2026-01-27T07:19:35.175275Z 44 Query select 1
2026-01-27T07:19:43.689707Z 45 Query show tables
2026-01-27T07:19:45.175046Z 39 Query select 1
2026-01-27T07:19:48.150394Z 42 Query show tables
2026-01-27T07:19:55.175646Z 40 Query select 1
2026-01-27T07:20:05.174974Z 41 Query select 1
2026-01-27T07:20:15.175661Z 46 Query select 1
2026-01-27T07:20:21.192739Z 43 Query select * from t1
2026-01-27T07:20:25.176398Z 44 Query select 1
2026-01-27T07:20:35.174779Z 45 Query select 1
2026-01-27T07:20:39.849680Z 12 Query BEGIN
2026-01-27T07:20:39.869216Z 12 Query COMMIT /* implicit, from Xid_log_event */
2026-01-27T07:20:45.174625Z 39 Query select 1
四、MHA
1.搭建MHA架构
(1)配置MHA manager 节点
#安装MHA的安装包
[root@mysql-mha ~]# yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[root@mysql-mha ~]# yum -y install mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
#在所有节点实现相互之间ssh key (每个节点上需要安装rsync软件包)
[root@mysql-mha ~]# ssh-keygen
[root@mysql-mha ~]# ssh-copy-id 127.0.0.1
[root@mysql-mha ~]# rsync -av .ssh 10.0.0.8:/root/
[root@mysql-mha ~]# rsync -av .ssh 10.0.0.18:/root/
[root@mysql-mha ~]# rsync -av .ssh 10.0.0.28:/root/
#建立配置文件
[root@mysql-mha ~]# mkdir /etc/mastermha
[root@mysql-mha ~]# vim /etc/mastermha/app1.cnf
[server default]
user=mhauser #用于远程连接MySQL所有节点的用户,需要管理员权限
password=123456
manager_workdir=/data/mastermha/app1/
manager_log=/data/mastermha/app1/manager.log
remote_workdir=/data/mastermha/app1/
ssh_user=root #用于实现远程ssh基于KEY的连接,访问二进制日志
repl_user=repluser #主从复制的用户信息
repl_password=123456
ping_interval=1 #健康性检查的时间间隔
secondary_check_script = masterha_secondary_check -s 10.0.0.18 -s 10.0.0.28 --user=root #主节点二次检测脚本
master_ip_failover_script=/usr/local/bin/master_ip_failover #切换VIP的perl脚本,不支持跨网络,也可用Keepalived实现
report_script=/usr/local/bin/sendmail.sh
check_repl_delay=0
#默认值为1,表示如果slave中从库落后主库relay_log超过100M,主库不会选择这个从库为新的master,
#因为这个从库进行恢复需要很长的时间。通过设置参数check_repl_delay=0,mha触发主从切换时会忽略复制的延时,
#对于设置candidata_master=1的从库非常有用,这样确保这个从库一定能成为最新的master。
master_binlog_dir=/data/mysql/logbin/
[server1]
candidate_master=1
hostname=10.0.0.8
[server2]
hostname=10.0.0.18 #控制故障转移时主节点选举优先级
candidate_master=1
[server3]
hostname=10.0.0.28
#相关脚本
[root@mysql-mha ~]# vim /usr/local/bin/sendmail.sh #确保安装failover邮件,并配置
echo "MHA is failover!" | mail -s "MHA Warning" 1953936927@qq.com
[root@mysql-mha ~]# vim /usr/local/bin/secondary_check_script
#!/bin/bash
/usr/bin/masterha_secondary_check -s 10.0.0.18 -p 22
[root@mysql-mha ~]# vim /usr/local/bin/master_ip_failover #确保所有节点安装net-tools
#!/usr/bin/env perl
# Copyright (C) 2011 DeNA Co.,Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
## Note: This is a sample script and is not complete. Modify the script based on your environment.
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
use MHA::DBHelper;
my (
$command, $ssh_user, $orig_master_host,
$orig_master_ip, $orig_master_port, $new_master_host,
$new_master_ip, $new_master_port, $new_master_user,
$new_master_password
);
my $vip = '10.0.0.100/24';
my $key = "1";
my $ssh_start_vip = "/usr/sbin/ifconfig ens160:$key $vip";
my $ssh_stop_vip = "/usr/sbin/ifconfig ens160:$key down";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
'new_master_user=s' => \$new_master_user,
'new_master_password=s' => \$new_master_password,
);
exit &main();
sub main {
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
# updating global catalog, etc
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
&stop_vip(); #若出错,删掉
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
#授予运行权限
[root@mysql-mha ~]# chmod +x /usr/local/bin/sendmail.sh
[root@mysql-mha ~]# chmod +x /usr/local/bin/master_ip_failover
#同步给MySQL节点
[root@mysql-mha ~]# scp /usr/local/bin/master_ip_failover root@10.0.0.8:/usr/local/bin/
[root@mysql-mha ~]# scp /usr/local/bin/master_ip_failover root@10.0.0.18:/usr/local/bin/
[root@mysql-mha ~]# scp /usr/local/bin/master_ip_failover root@10.0.0.28:/usr/local/bin/
[root@mysql-mha ~]# ssh root@10.0.0.8 "chmod +x /usr/local/bin/master_ip_failover"
[root@mysql-mha ~]# ssh root@10.0.0.18 "chmod +x /usr/local/bin/master_ip_failover"
[root@mysql-mha ~]# ssh root@10.0.0.28 "chmod +x /usr/local/bin/master_ip_failover"
(2)配置master节点 (在主从复制基础上)
#安装MHA节点包
[root@MySQL-master ~]# yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
#修改配置文件
[root@MySQL-master ~]# more /etc/my.cnf
[mysqld]
server-id=1
log-bin=/data/mysql/logbin/mysql-bin
skip_name_resolve = 1 #禁用 DNS 解析、仅认 IP,提升连接效率并避免 DNS 故障
general_log #观察结果,非必须项,生产无需启用
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
default_storage_engine=InnoDB
character_set_server=utf8mb4
[mysql]
user=root
password=root@123456
socket=/data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
#创建远程连接管理员用户
[root@MySQL-master ~]# mysql
mysql> create user mhauser@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (0.05 sec)
mysql> ALTER USER 'mhauser'@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.00 sec)
mysql> grant all on *.* to mhauser@'10.0.0.%';
Query OK, 0 rows affected (0.01 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
#重启生效
[root@MySQL-master ~]# systemctl restart mysqld
#配置VIP
(3)配置slave节点
#安装MHA 节点包
[root@MySQL-slave01 ~]# yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
#修改配置文件
[root@MySQL-slave01 ~]# vim /etc/my.cnf
[mysqld]
server-id=2
read_only
relay_log_purge=0 #禁用 MySQL 从库中继日志(relay log)的自动清理功能
relay_log_recovery=1 # 从库重启后,自动清理旧 relay log 并重新从主库获取
skip_name_resolve=1 #禁止反向解析
general_log
log-bin = /data/mysql/logbin/mysql-bin
datadir = /data/mysql
socket = /data/mysql/mysql.sock
log-error = /data/mysql/mysql.log
pid-file = /data/mysql/mysql.pid
default_storage_engine = InnoDB
character_set_server = utf8mb4
[mysql]
user=root
password=root@123456
socket = /data/mysql/mysql.sock
default-character-set = utf8mb4
[client]
socket=/data/mysql/mysql.sock
#重启生效
[root@MySQL-slave01 ~]# systemctl restart mysqld
(4)在MHA manager节点启动
[root@mysql-mha ~]# masterha_check_ssh --conf=/etc/mastermha/app1.cnf
Fri Jan 30 10:25:50 2026 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Jan 30 10:25:50 2026 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Fri Jan 30 10:25:50 2026 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Fri Jan 30 10:25:50 2026 - [info] Starting SSH connection tests..
Fri Jan 30 10:25:51 2026 - [debug]
Fri Jan 30 10:25:50 2026 - [debug] Connecting via SSH from root@10.0.0.8(10.0.0.8:22) to root@10.0.0.18(10.0.0.18:22)..
Fri Jan 30 10:25:50 2026 - [debug] ok.
Fri Jan 30 10:25:50 2026 - [debug] Connecting via SSH from root@10.0.0.8(10.0.0.8:22) to root@10.0.0.28(10.0.0.28:22)..
Fri Jan 30 10:25:51 2026 - [debug] ok.
Fri Jan 30 10:25:53 2026 - [debug]
Fri Jan 30 10:25:51 2026 - [debug] Connecting via SSH from root@10.0.0.28(10.0.0.28:22) to root@10.0.0.8(10.0.0.8:22)..
Fri Jan 30 10:25:52 2026 - [debug] ok.
Fri Jan 30 10:25:52 2026 - [debug] Connecting via SSH from root@10.0.0.28(10.0.0.28:22) to root@10.0.0.18(10.0.0.18:22)..
Fri Jan 30 10:25:53 2026 - [debug] ok.
Fri Jan 30 10:25:53 2026 - [debug]
Fri Jan 30 10:25:50 2026 - [debug] Connecting via SSH from root@10.0.0.18(10.0.0.18:22) to root@10.0.0.8(10.0.0.8:22)..
Fri Jan 30 10:25:51 2026 - [debug] ok.
Fri Jan 30 10:25:51 2026 - [debug] Connecting via SSH from root@10.0.0.18(10.0.0.18:22) to root@10.0.0.28(10.0.0.28:22)..
Fri Jan 30 10:25:52 2026 - [debug] ok.
Fri Jan 30 10:25:53 2026 - [info] All SSH connection tests passed successfully.
[root@mysql-mha ~]# masterha_check_repl --conf=/etc/mastermha/app1.cnf
Fri Jan 30 10:26:03 2026 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Jan 30 10:26:03 2026 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Fri Jan 30 10:26:03 2026 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Fri Jan 30 10:26:03 2026 - [info] MHA::MasterMonitor version 0.58.
Fri Jan 30 10:26:05 2026 - [info] GTID failover mode = 0
Fri Jan 30 10:26:05 2026 - [info] Dead Servers:
Fri Jan 30 10:26:05 2026 - [info] Alive Servers:
Fri Jan 30 10:26:05 2026 - [info] 10.0.0.8(10.0.0.8:3306)
Fri Jan 30 10:26:05 2026 - [info] 10.0.0.18(10.0.0.18:3306)
Fri Jan 30 10:26:05 2026 - [info] 10.0.0.28(10.0.0.28:3306)
Fri Jan 30 10:26:05 2026 - [info] Alive Slaves:
Fri Jan 30 10:26:05 2026 - [info] 10.0.0.18(10.0.0.18:3306) Version=8.0.27 (oldest major version between slaves) log-bin:enabled
Fri Jan 30 10:26:05 2026 - [info] Replicating from 10.0.0.8(10.0.0.8:3306)
Fri Jan 30 10:26:05 2026 - [info] Primary candidate for the new Master (candidate_master is set)
Fri Jan 30 10:26:05 2026 - [info] 10.0.0.28(10.0.0.28:3306) Version=8.0.27 (oldest major version between slaves) log-bin:enabled
Fri Jan 30 10:26:05 2026 - [info] Replicating from 10.0.0.8(10.0.0.8:3306)
Fri Jan 30 10:26:05 2026 - [info] Current Alive Master: 10.0.0.8(10.0.0.8:3306)
Fri Jan 30 10:26:05 2026 - [info] Checking slave configurations..
Fri Jan 30 10:26:05 2026 - [info] Checking replication filtering settings..
Fri Jan 30 10:26:05 2026 - [info] binlog_do_db= , binlog_ignore_db=
Fri Jan 30 10:26:05 2026 - [info] Replication filtering check ok.
Fri Jan 30 10:26:05 2026 - [info] GTID (with auto-pos) is not supported
Fri Jan 30 10:26:05 2026 - [info] Starting SSH connection tests..
Fri Jan 30 10:26:07 2026 - [info] All SSH connection tests passed successfully.
Fri Jan 30 10:26:07 2026 - [info] Checking MHA Node version..
Fri Jan 30 10:26:08 2026 - [info] Version check ok.
Fri Jan 30 10:26:08 2026 - [info] Checking SSH publickey authentication settings on the current master..
Fri Jan 30 10:26:09 2026 - [info] HealthCheck: SSH to 10.0.0.8 is reachable.
Fri Jan 30 10:26:09 2026 - [info] Master MHA Node version is 0.58.
Fri Jan 30 10:26:09 2026 - [info] Checking recovery script configurations on 10.0.0.8(10.0.0.8:3306)..
Fri Jan 30 10:26:09 2026 - [info] Executing command: save_binary_logs --command=test --start_pos=4 --binlog_dir=/data/mysql/logbin/ --output_file=/data/mastermha/app1//save_binary_logs_test --manager_version=0.58 --start_file=mysql-bin.000007
Fri Jan 30 10:26:09 2026 - [info] Connecting to root@10.0.0.8(10.0.0.8:22)..
Creating /data/mastermha/app1 if not exists.. ok.
Checking output directory is accessible or not..
ok.
Binlog found at /data/mysql/logbin/, up to mysql-bin.000007
Fri Jan 30 10:26:09 2026 - [info] Binlog setting check done.
Fri Jan 30 10:26:09 2026 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers..
Fri Jan 30 10:26:09 2026 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=10.0.0.18 --slave_ip=10.0.0.18 --slave_port=3306 --workdir=/data/mastermha/app1/ --target_version=8.0.27 --manager_version=0.58 --relay_dir=/data/mysql --current_relay_log=MySQL-slave01-relay-bin.000014 --slave_pass=xxx
Fri Jan 30 10:26:09 2026 - [info] Connecting to root@10.0.0.18(10.0.0.18:22)..
Checking slave recovery environment settings..
Relay log found at /data/mysql, up to MySQL-slave01-relay-bin.000014
Temporary relay log file is /data/mysql/MySQL-slave01-relay-bin.000014
Checking if super_read_only is defined and turned on.. not present or turned off, ignoring.
Testing mysql connection and privileges..
mysql: [Warning] Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Fri Jan 30 10:26:10 2026 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=10.0.0.28 --slave_ip=10.0.0.28 --slave_port=3306 --workdir=/data/mastermha/app1/ --target_version=8.0.27 --manager_version=0.58 --relay_dir=/data/mysql --current_relay_log=MySQL-slave02-relay-bin.000009 --slave_pass=xxx
Fri Jan 30 10:26:10 2026 - [info] Connecting to root@10.0.0.28(10.0.0.28:22)..
Checking slave recovery environment settings..
Relay log found at /data/mysql, up to MySQL-slave02-relay-bin.000009
Temporary relay log file is /data/mysql/MySQL-slave02-relay-bin.000009
Checking if super_read_only is defined and turned on.. not present or turned off, ignoring.
Testing mysql connection and privileges..
mysql: [Warning] Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Fri Jan 30 10:26:12 2026 - [info] Slaves settings check done.
Fri Jan 30 10:26:12 2026 - [info]
10.0.0.8(10.0.0.8:3306) (current master)
+--10.0.0.18(10.0.0.18:3306)
+--10.0.0.28(10.0.0.28:3306)
Fri Jan 30 10:26:12 2026 - [info] Checking replication health on 10.0.0.18..
Fri Jan 30 10:26:12 2026 - [info] ok.
Fri Jan 30 10:26:12 2026 - [info] Checking replication health on 10.0.0.28..
Fri Jan 30 10:26:12 2026 - [info] ok.
Fri Jan 30 10:26:12 2026 - [info] Checking master_ip_failover_script status:
Fri Jan 30 10:26:12 2026 - [info] /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=10.0.0.8 --orig_master_ip=10.0.0.8 --orig_master_port=3306
Checking the Status of the script.. OK
Fri Jan 30 10:26:12 2026 - [info] OK.
Fri Jan 30 10:26:12 2026 - [warning] shutdown_script is not defined.
Fri Jan 30 10:26:12 2026 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.
[root@mysql-mha ~]# masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 is stopped(2:NOT_RUNNING).
[root@mysql-mha ~]# nohup masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover &> /dev/null &
[1] 2639
[::]:* users:(("sshd",pid=823,fd=4))
[root@mysql-mha ~]# masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 (pid:2639) is running(0:PING_OK), master:10.0.0.8
[root@mysql-mha ~]# jobs -l
[1]+ 2639 Running nohup masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover &>/dev/null &
(5)配置MHA进程开机自启
#关闭后台运行
[root@mysql-mha ~]# jobs -l
[1]+ 2639 Running nohup masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover &>/dev/null &
[root@mysql-mha ~]# masterha_stop --conf /etc/mastermha/app1.cnf
Stopped app1 successfully.
[1]+ Exit 1 nohup masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover &>/dev/null
#service启动配置文件
[root@mysql-mha ~]# vim /usr/lib/systemd/system/mha-manager.service
[Unit]
Description=MHA MySQL High Availability Manager
After=network.target mysqld.service
[Service]
Type=simple
User=root
ExecStart=/usr/bin/masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover
ExecStop=/usr/bin/masterha_stop --conf=/etc/mastermha/app1.cnf
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
#配置生效,开机自启
[root@mysql-mha ~]# systemctl daemon-reload
[root@mysql-mha ~]# systemctl enable --now mha-manager
[root@mysql-mha ~]# systemctl status mha-manager
[root@mysql-mha ~]# masterha_check_status --conf /etc/mastermha/app1.cnf
app1 (pid:18804) is running(0:PING_OK), master:10.0.0.8
#查看MHA日志
[root@mysql-mha ~]# tail -f /data/mastermha/app1/manager.log
Fri Jan 30 14:56:11 2026 - [info] Checking master_ip_failover_script status:
Fri Jan 30 14:56:11 2026 - [info] /usr/local/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=10.0.0.8 --orig_master_ip=10.0.0.8 --orig_master_port=3306
Checking the Status of the script.. OK
Fri Jan 30 14:56:11 2026 - [info] OK.
Fri Jan 30 14:56:11 2026 - [warning] shutdown_script is not defined.
Fri Jan 30 14:56:11 2026 - [info] Set master ping interval 1 seconds.
Fri Jan 30 14:56:11 2026 - [info] Set secondary check script: /usr/local/bin/secondary_check_script
Fri Jan 30 14:56:11 2026 - [info] Starting ping health check on 10.0.0.8(10.0.0.8:3306)..
Fri Jan 30 14:56:11 2026 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
2.故障演练
(1)实例1:当主节点出现故障时
#停止主节点MySQL
[root@MySQL-master ~]# systemctl stop mysqld
[root@MySQL-master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:e7:18:28 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 10.0.0.8/24 brd 10.0.0.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fee7:1828/64 scope link noprefixroute
valid_lft forever preferred_lft forever
#查看从节点状态
[root@MySQL-slave01 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:5a:81:9b brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 10.0.0.18/24 brd 10.0.0.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet 10.0.0.100/24 brd 10.0.0.255 scope global secondary ens160:1 #vip漂移到了slave01 10.0.0.18上
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe5a:819b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@MySQL-slave02 ~]# mysql
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.18 #从库slave01 当选为主库
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000005
Read_Master_Log_Pos: 156
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000005
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#查看MHA状态和日志
[root@mysql-mha ~]# systemctl status mha-manager #当 master down机后,mha管理程序自动退出
● mha-manager.service - MHA MySQL High Availability Manager
Loaded: loaded (/usr/lib/systemd/system/mha-manager.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2026-02-02 15:12:37 CST; 4min 8s ago
Process: 19443 ExecStop=/usr/bin/masterha_stop --conf=/etc/mastermha/app1.cnf (code=exited, status=0/SUCCESS)
Process: 19347 ExecStart=/usr/bin/masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover (code=exited, status=0/SUCCESS)
Main PID: 19347 (code=exited, status=0/SUCCESS)
Feb 02 15:12:13 mysql-mha masterha_manager[19347]: Mon Feb 2 15:12:13 2026 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Feb 02 15:12:13 mysql-mha masterha_manager[19347]: Mon Feb 2 15:12:13 2026 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Feb 02 15:12:21 mysql-mha masterha_manager[19347]: Creating /data/mastermha/app1 if not exists.. ok.
Feb 02 15:12:21 mysql-mha masterha_manager[19347]: Checking output directory is accessible or not..
Feb 02 15:12:21 mysql-mha masterha_manager[19347]: ok.
Feb 02 15:12:21 mysql-mha masterha_manager[19347]: Binlog found at /data/mysql/logbin/, up to mysql-bin.000006
Feb 02 15:12:25 mysql-mha masterha_manager[19347]: Mon Feb 2 15:12:25 2026 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Feb 02 15:12:25 mysql-mha masterha_manager[19347]: Mon Feb 2 15:12:25 2026 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Feb 02 15:12:25 mysql-mha masterha_manager[19347]: Mon Feb 2 15:12:25 2026 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Feb 02 15:12:37 mysql-mha masterha_stop[19443]: MHA Manager is not running on app1(2:NOT_RUNNING).
[root@mysql-mha ~]# cat /data/mastermha/app1/manager.log #mha管理日志中显示的故障转移
app1: MySQL Master failover 10.0.0.8(10.0.0.8:3306) to 10.0.0.18(10.0.0.18:3306) succeeded
Master 10.0.0.8(10.0.0.8:3306) is down!
Check MHA Manager logs at mysql-mha:/data/mastermha/app1/manager.log for details.
Started automated(non-interactive) failover.
Invalidated master IP address on 10.0.0.8(10.0.0.8:3306)
The latest slave 10.0.0.18(10.0.0.18:3306) has all relay logs for recovery.
Selected 10.0.0.18(10.0.0.18:3306) as a new master.
10.0.0.18(10.0.0.18:3306): OK: Applying all logs succeeded.
10.0.0.18(10.0.0.18:3306): OK: Activated master IP address.
10.0.0.28(10.0.0.28:3306): This host has the latest relay log events.
Generating relay diff files from the latest slave succeeded.
10.0.0.28(10.0.0.28:3306): OK: Applying all logs succeeded. Slave started, replicating from 10.0.0.18(10.0.0.18:3306)
10.0.0.18(10.0.0.18:3306): Resetting slave info succeeded.
Master failover to 10.0.0.18(10.0.0.18:3306) completed successfully.
#自动修改manager节点上的配置文件,将master剔除
[root@mysql-mha ~]# cat /etc/mastermha/app1.cnf
[server default]
check_repl_delay=0
manager_log=/data/mastermha/app1/manager.log
manager_workdir=/data/mastermha/app1/
master_binlog_dir=/data/mysql/logbin/
master_ip_failover_script=/usr/local/bin/master_ip_failover
password=123456
ping_interval=1
remote_workdir=/data/mastermha/app1/
repl_password=123456
repl_user=repluser
report_script=/usr/local/bin/sendmail.sh
secondary_check_script=masterha_secondary_check -s 10.0.0.18 -s 10.0.0.28 --user=root
ssh_user=root
user=mhauser
[server2]
candidate_master=1
hostname=10.0.0.18
[server3]
hostname=10.0.0.28
#重新启动10.0.0.8,使其成为10.0.0.18的从库
[root@MySQL-master ~]# systemctl start mysqld
[root@MySQL-slave01 ~]# mysqldump -uroot -p -A -F --master-data=1 --single-transaction > /data/all.sql
[root@MySQL-slave01 ~]# mysql
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000006 | 156 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.02 sec)
[root@MySQL-master ~]# vim /data/all.sq
CHANGE MASTER TO
MASTER_HOST='10.0.0.18',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=156;
[root@MySQL-master ~]# mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /data/all.sql
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.14 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.18
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000006
Read_Master_Log_Pos: 156
Relay_Log_File: MySQL-master-relay-bin.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000006
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#重新启动MHA-manager
[root@mysql-mha ~]# systemctl start mha-manager
[root@mysql-mha ~]# systemctl status mha-manager
● mha-manager.service - MHA MySQL High Availability Manager
Loaded: loaded (/usr/lib/systemd/system/mha-manager.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2026-02-02 15:26:11 CST; 2s ago
Process: 19443 ExecStop=/usr/bin/masterha_stop --conf=/etc/mastermha/app1.cnf (code=exited, status=0/SUCCESS)
Main PID: 19583 (perl)
CGroup: /system.slice/mha-manager.service
├─19583 perl /usr/bin/masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover
├─19590 perl /usr/bin/masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover
├─19591 sh -c ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o BatchMode=yes -o ConnectTimeout=5 -p 22 root@10.0.0.18 "ssh -o StrictHostKeyChecking=no -o PasswordAuthenticatio...
├─19592 ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o BatchMode=yes -o ConnectTimeout=5 -p 22 root@10.0.0.18 ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o...
├─19593 perl /usr/bin/masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover
├─19594 sh -c ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o BatchMode=yes -o ConnectTimeout=5 -p 22 root@10.0.0.28 "ssh -o StrictHostKeyChecking=no -o PasswordAuthenticatio...
└─19595 ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o BatchMode=yes -o ConnectTimeout=5 -p 22 root@10.0.0.28 ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o...
Feb 02 15:26:11 mysql-mha systemd[1]: Started MHA MySQL High Availability Manager.
Feb 02 15:26:11 mysql-mha masterha_manager[19583]: Mon Feb 2 15:26:11 2026 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Feb 02 15:26:11 mysql-mha masterha_manager[19583]: Mon Feb 2 15:26:11 2026 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Feb 02 15:26:11 mysql-mha masterha_manager[19583]: Mon Feb 2 15:26:11 2026 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
[root@mysql-mha ~]# masterha_check_status --conf /etc/mastermha/app1.cnf
app1 (pid:19583) is running(0:PING_OK), master:10.0.0.18
(2)注意事项
#如果重启出错,需要删除下面文件再执行MHA
[root@mysql-mha ~]# rm -f /data/mastermha/app1/app1.failover.error
#MHA只能漂移一次,如果多次使用必须删除以下文件,要不MHA不可重用
[root@mysql-mha ~]# rm -rf /data/mastermha/app1/ #mha_master自己的工作路径
[root@mysql-mha ~]# rm -rf /data/mastermha/app1/manager.log #mha_master自己的日志文件
[root@MySQL-master ~]# rm -rf /data/mastermha/app1/ #每个远程主机即三个节点的的工作目录