MySQL主备模式(互相复制)配置

157 阅读3分钟

高可用方案

 2台互为主备,互相复制。

 注意: 

keepalived + mysql

单独的2台机器,部署MySQL,配备单独的vip 

keepalived配置妥当,注意keepalived绑定的网卡,在keepalived.conf 配置 interface 

2台强制设置readonly给业务用户(因为root用户不受限制)

主备+互相复制配置过程

原单机操作

mysqldump -h127.0.0.1 -P3306 -uroot -p'密码' --single-transaction -E -R --triggers --all-databases --master-data=2 --add-drop-database --add-drop-table --verbose> 20221020-1.sql

在master和slave执行

1.停掉slb,防止执行过程中,有数据写入(如果没有使用keepalived,可以暂时把mysql端口修改为3307)
    docker stop keepalived
2.删除MySQL容器    
    docker-compose down
3.删除(或备份到别处)data目录,新建MySQL的数据目录data,重建容器
    docker-compose up -d
4.sql复制到容器里面 
    docker cp 20221020-1.sql mysql_container:/.
5. 在master和slave,都同时执行导入初始化语句,此时2个MySQL还不通
    source 20221020-1.sql;
6. 退出容器,重启mysql 
    docker restart mysql_server
7. 进入容器,检查slave账号是否存在,如果不存在分别创建slave账号    select user from mysql.user;

在master执行

1.挑选一台为master
    show master status\G; 
2.记下 master的 Executed_Gtid_Set

在slave执行

1.reset master;
2.stop slave;
3.reset slave all;
4.show slave status\G;
5.show master status\G;
6.change master to master_auto_position=0;
7.SET @@GLOBAL.GTID_PURGED='上一步的Executed_Gtid_Set的值'; (使用20221020-1.sql文件头部的GTID的值也可以)
8.CHANGE MASTER TO MASTER_HOST='ip', MASTER_PORT=3306, MASTER_USER='slave', MASTER_PASSWORD='密码', master_auto_position=1;
9.start slave;
10.show slave status\G;检查复制状态是否有2个yes

回到master执行

1.stop slave;
2.reset slave all;
3.show slave status\G;
4.change master to master_auto_position=0;
5.CHANGE MASTER TO MASTER_HOST='ip', MASTER_PORT=3306, MASTER_USER='slave', MASTER_PASSWORD='密码', master_auto_position=1;
6.start slave;
7.show slave status\G;检查复制状态是否有2个yes

master和slave都执行

1.show slave status\G;检查复制状态是否有2个yes
2.show variables like 'read_only';
    检查2台机器的read_only 状态,如果没有需要设置其中一个为read_only(配合使用脚本实现)

监控MySQL的slave,设置read_only(高可用的一部分设置)

配置定时任务脚本check_mysql_read_only.sh

#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

# 因为crontab最小间隔是1分钟,这里设置1分钟内执行11次
for((i=1;i<=11;i++));
do
    echo $i >> /check_mysql_read_only.log

    ip a| grep vip
    if [ $? -eq 0 ]
    then
      # echo "-----`date "+%Y-%m-%d %H:%M:%S"` 当前节点有vip,不做处理-----" >> /check_mysql_read_only.log
      
      # 如果是vip,那么就不停的设置为OFF
      /usr/local/sbin/docker exec  mysql_server mysql -uroot -p'密码' -e "set global read_only=0" >> /check_mysql_read_only.log 
      echo "-----`date "+%Y-%m-%d %H:%M:%S"` 当前节点有vip,设置read_only为OFF-----" >> /check_mysql_read_only.log
    else
     /usr/local/sbin/docker exec  mysql_server mysql -uroot -p'密码' -e "set global read_only=1" >> /check_mysql_read_only.log 
      echo "-----`date "+%Y-%m-%d %H:%M:%S"` 当前节点没有vip,设置read_only为ON-----" >> /check_mysql_read_only.log
    fi
    sleep 5
done

# read_only 属性值,不会通过binlog主从同步

使用crontab执行

crontab -e 增加* * * * * bash /check_mysql_read_only.sh

清理设置read_only设置的日志

配置清理日志脚本 check_mysql_read_only_auto_clean_log.sh

#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

file_size=`ls -la /check_mysql_read_only.log | awk '{print $5}'`

# 如果文件大于30M,那么删除
if [ $file_size -ge 31457280 ]
then
    rm -rf /check_mysql_read_only.log
    printf "\n-----`date "+%Y-%m-%d %H:%M:%S"` check_mysql_read_only.log size $file_size 大于30M 删除此文件\n\n" >> /check_mysql_read_only.log
else
    printf "\n-----`date "+%Y-%m-%d %H:%M:%S"` check_mysql_read_only.log size $file_size 小于30M 不做处理\n\n" >> /check_mysql_read_only.log
fi

使用crontab执行

crontab 配置 
* * * * * bash /check_mysql_read_only_auto_clean_log.sh

read_only设置无法生效问题(高可用的一部分设置)

read_only对于带有super权限的用户无效。所以不要使用带有super权限的用户。

1. 如myapp用户,root下执行下面语句,撤销super权限。
    REVOKE Super ON *.* FROM 'myapp'@'%';
    
2. 执行 set global read_only=1(即ON)后,myapp就无法执行insertupdatedelete了。

3. 执行 set global read_only=0(即OFF)后,myapp又恢复了读写权限。

测试

show variables like 'super_read_only'
show variables like 'read_only'
show slave status\G