MySQL主从复制原理:
1. 主从复制的基本概念
-
主服务器(Master):负责处理所有的写操作(INSERT、UPDATE、DELETE),并将这些操作记录到二进制日志(binary log)中。
-
从服务器(Slave):从主服务器读取二进制日志,并执行日志中的操作以保持数据同步。
2. 工作流程
-
写入操作:
-
客户端向主服务器发送写入请求(如 INSERT、UPDATE、DELETE)。
-
主服务器执行操作并将这些操作记录到二进制日志中。
-
-
日志传输:
-
从服务器定期连接到主服务器,获取二进制日志的更新。
-
从服务器会记录当前已处理的日志位置,以便下次连接时从该位置继续获取新的日志。
-
-
执行日志:
-
从服务器读取主服务器的二进制日志,并将日志中的操作应用到自己的数据表中,以保持与主服务器的数据一致性。
-
3. 复制类型
MySQL 支持几种不同的复制类型:
-
异步复制:从服务器在接收到主服务器的日志后,不需要立即确认,主服务器可以继续处理其他请求。这种方式可能导致数据延迟。
-
半同步复制:主服务器在发送日志后,等待至少一个从服务器确认已接收日志,然后再继续处理请求。这种方式可以减少数据丢失的风险。
-
全同步复制:所有从服务器在接收到日志后都必须确认,主服务器才会继续处理请求。这种方式会增加延迟,但确保数据一致性。
在 MySQL 主从复制的原理中,有两个重要的线程负责复制过程:I/O 线程和 SQL 线程。以下是对这两个线程的详细说明:
1. I/O 线程
-
功能:I/O 线程负责从主服务器读取二进制日志并将其写入从服务器的中继日志(relay log)。
-
工作流程:
-
从服务器连接到主服务器。
-
请求主服务器的二进制日志。
-
将接收到的日志写入中继日志。
-
记录当前的日志位置,以便下次连接时可以从该位置继续读取。
-
2. SQL 线程
-
功能:SQL 线程负责从中继日志中读取事件并将其应用到从服务器的数据库中。
-
工作流程:
-
从中继日志中读取事件(如 INSERT、UPDATE、DELETE)。
-
执行这些事件以更新从服务器的数据库。
-
更新已处理的日志位置,以确保不会重复执行相同的事件。
-
3. 线程的协作
-
I/O 线程和 SQL 线程是并行运行的,I/O 线程不断从主服务器获取新的日志,而 SQL 线程则处理中继日志中的事件。这种设计允许从服务器在处理数据的同时继续接收新的日志,从而提高了复制的效率。
4. 监控线程状态
可以通过 SHOW SLAVE STATUS\G
命令查看这两个线程的状态,包括它们是否正在运行、是否有错误、当前的日志位置等信息。关键字段包括:
-
Slave_IO_Running
:指示 I/O 线程是否正在运行。 -
Slave_SQL_Running
:指示 SQL 线程是否正在运行。 -
Relay_Log_Space
:中继日志的总大小。
查看slave1的同步状态,监控这两个线程是否都正常。
在 /etc/zabbix/script/目录下存放监控主从复制状态脚本
cd /etc/zabbix/script/
cat mysql_slvae_status.sh #!/bin/bash
#监控MySQL主从同步线程状态
USER="slave"
PASSWD="Zabbix@root818"
HOST="192.168.158.136"
NAME=$1
MYSQL_CMD="/usr/local/mysql/bin/mysql"
function IO {Slave_IO_Running=`$MYSQL_CMD -h$HOST -u$USER -p$PASSWD -e "show slave status\G;" 2> /dev/null |grep Slave_IO_Running |awk '{print $2}'`if [[ $Slave_IO_Running == "Yes" ]];thenecho 0elseecho 1fi
}
function SQL {Slave_SQL_Running=`$MYSQL_CMD -h$HOST -u$USER -p$PASSWD -e "show slave status\G;" 2> /dev/null |grep Slave_SQL_Running: |awk '{print $2}'`if [[ $Slave_SQL_Running == "Yes" ]];thenecho 0elseecho 1fi
}
case $NAME inio)IO;;sql)SQL;;*)echo -e "Usage: $0 [io | sql]"
esac
在/etc/zabbix/zabbix_agent2.d/plugins.d/目录下编写自定义监控配置文件
cat userparameter_mysql_slave.conf
# 获取MySQL slave状态
UserParameter=mysql.slave[*],/etc/zabbix/script/mysql_slvae_status.sh $1
重启zabbix-agent2
在zabbix-server端进行测试,看是否能够成功获取到值,通过上面的脚本,这里为0即表示正常,为1即表示不正常。
[root@zabbix-server ~]# zabbix_get -s 192.168.158.135 -k mysql.slave[io]
0
[root@zabbix-server ~]# zabbix_get -s 192.168.158.135 -k mysql.slave[sql]
0
server端web配置#
1)配置Slave_IO_Running线程监控项
2)配置Slave_SQL_Running线程监控项
3)配置Slave_IO_Running线程的触发器
4)配置Slave_SQL_Running线程的触发器
5)配置告警媒介
1、创建钉钉群聊,并添加机器人
2、创建目录和脚本
mkdir /usr/lib/zabbix/alertscripts/
mkdir /usr/lib/zabbix/alertscripts/log
touch /usr/lib/zabbix/alertscripts/log/dingding.log
chown zabbix:zabbix /usr/lib/zabbix/alertscripts/log/dingding.log
chown zabbix:zabbix /usr/lib/zabbix/alertscripts/dingding.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import json
import sys
import os
import datetime
#这个地址就是钉钉机器人的地址
webhook = "换成你钉钉机器人生成的地址"
user=sys.argv[1]
subject=sys.argv[2]
text=sys.argv[3]
data={"msgtype": "text","text": {"content": "%s%s"%(subject,text)},"at": {"atMobiles": [user],"isAtAll": False}
}
headers = {'Content-Type': 'application/json'}
x=requests.post(url=webhook,data=json.dumps(data),headers=headers)
if os.path.exists("/usr/lib/zabbix/alertscripts/log/dingding.log"):f=open("/usr/lib/zabbix/alertscripts/log/dingding.log","a+")
else:f=open("/usr/lib/zabbix/alertscripts/log/dingding.log","w+")
f.write("\n"+"--"*30)
if x.json()["errcode"] == 0:f.write("\n"+str(datetime.datetime.now())+" "+str(user)+" "+"发送成功"+"\n"+str(text))f.close()
else:f.write("\n"+str(datetime.datetime.now())+" "+str(user)+" "+"发送失败"+"\n"+str(text))f.close()
3、测试这个脚本
我这里发送成功,并且钉钉机器人推送了消息
6)配置触发动作
配置动作中需要执行的动作(发送消息给管理员)
服务器:{HOST.NAME}发生: {TRIGGER.NAME}故障!
##服务器:{HOST.NAME}发生: {TRIGGER.NAME}故障!
告警主机:{HOST.NAME}
告警地址:{HOST.IP}
监控项目:{ITEM.NAME}
监控取值:{ITEM.LASTVALUE}
告警等级:{TRIGGER.SEVERITY}
当前状态:{TRIGGER.STATUS}
告警信息:{TRIGGER.NAME}
告警时间:{EVENT.DATE} {EVENT.TIME}
事件ID:{EVENT.ID}
配置状态恢复时的操作(同样发送消息给管理员)
服务器:{HOST.NAME}: {TRIGGER.NAME}已恢复!
告警主机:{HOST.NAME}
告警地址:{HOST.IP}
监控项目:{ITEM.NAME}
监控取值:{ITEM.LASTVALUE}
告警等级:{TRIGGER.SEVERITY}
当前状态:{TRIGGER.STATUS}
告警信息:{TRIGGER.NAME}
告警时间:{EVENT.DATE} {EVENT.TIME}
恢复时间:{EVENT.RECOVERY.DATE} {EVENT.RECOVERY.TIME}
持续时间:{EVENT.AGE}
事件ID:{EVENT.ID}
配置用户告警媒介
最终查看监控项
7)模拟MySQL主从服务器复制故障
现在从服务器正常复制中
并且监控页面也没有相关告警消息
现在关掉了同步操作
监控页出现了告警
钉钉机器人也发来了告警
恢复主从复制
自此MySQL主从复制监控告警到推送钉钉群聊配置完成
如果发先监控页面的告警时间与服务器上的时间不对等,需要在监控页面上配置一下,我的是zabbix6.4版本,无需修改配置文件,也不需要重启服务。