主从复制其实是很脆弱的,有很多种情况都会导致主从关系停止,比如,我们设置了只同步某个库的数据,如果以后有其他数据库的加入,那么这个主从关系就会造成影响而停止;比如我们在从库中写入数据;主从复制过程中主库宕机了;主库的max_allowed_packet参数比从库大,一个较大的SQL语句在从库上无法执行。
上面这些因素都有可能导致主从关系的停止,因此设置一个主从关系的监控是很有必要的。

主从复制监控Shell脚本

这个脚本的基本思想是过滤含有”_Running”,”Behind_Master”字段的状态,如果发现与预期的不一致就报警。

Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates

  1. #!/bin/bash
  2. #Date:2022-01-10
  3. #Author:qinxi
  4. #version 1.0
  5. mysql_cmd="mysql -uroot -proot"
  6. errorno=(1158 1159 1008 1007 1062)
  7. while true
  8. do
  9. array=($(mysql -urep1 -proxe-walle.t -e "show slave status\G;"|egrep "_Running|Behind_Master"|awk '{print $NF}'))
  10. if [ "${array[0]}" == "Yes" -a "${array[1]}" == "Yes" -a "${array[2]}" == "0" ]
  11. then
  12. echo "MySQL is slave is ok"
  13. else
  14. for ((i=0;i<${#errorno[*]};i++))
  15. do
  16. if [ "${array[3]}" = "${errorno[$i]}" ];then
  17. $mysql_cmd -e "stop slave &&set global sql_slave_skip_counter=1;start slave;"
  18. fi
  19. done
  20. curl 'https://oapi.dingtalk.com/robot/send?access_token=0307673dfab8dc1cffc6a404913a077dcc9163c19318b3c977c70327aff2072b' \
  21. -H 'Content-Type: application/json' \
  22. -d '{"msgtype": "text",
  23. "text": {
  24. "content": "MySQL slave is not ok"
  25. }
  26. }'
  27. break
  28. fi
  29. sleep 20
  30. done

MySQL从库从主库上复制binlog文件内容到本地执行,在binlog上命令以event的形式存在,并非一个命令对应一个event。
以一个insert语句为例(引擎InnoDB、binglog_format=statement), 在binlog中实际上有三个event,分别为begin\insert\commit 。 命令类型都是Query_log_event,而set global sql_slave_skip_counter=N的意思,即为在start slave时,从当前位置起,跳过N个event,每跳过一个event,则N—。

如果当前的执行位置是某个insert语句开头,那使用 N=1实际上是从begin\insert\commit的第二个开始执行,这个insert语句还是不能被跳过?
实际上这里还有两个策略:
1、若N=1且当前event为BEGIN, 则N不变,跳过当前event继续。
2、若N=1且当前event处于一个事务之内(BEGIN之后,COMMIT之前),则N不变,跳过当前event继续。

说明:其实上面两个策略合起来就是一句话,当N=1时,会连续跳过若干个event,直到当前所在的事务结束。当然如果N>1,则每跳过一个event都要N—.

定时任务

  1. $ crontab -l
  2. */15 * * * * bash /data/shell/monitor-mysql.sh >>/tmp/mysql.log