不要用SECONDS_BEHIND_MASTER来衡量MYSQL主备的延迟时间,原因如下:


A:备库Seconds_behand_master值是通过将服务器当前的时间戳与二进制日志中的事件的时间戳对比得到的,所以只有在执行事件时才能报告延迟


B:如果备库复制线程没有运行,就会报延迟为null


C:一些错误,如主备的max_allowed_packet不匹配或者网络不稳定时,可能中断复制或者停止复制线程,但Seconds_behand_master将显示为0而不是显示错误


D:即使备库线程正在运行,备库有时候可能无法计算延迟时,如果发生这种情况,备库会报0或者null


E:一个较大的事务可能导致延迟波动,如:有一个事务更新数据长达一个小时,最后提交,这条更新将比它实际发生时间要晚一个小时才记录到二进制日志中,当备库执行这条语句时,会临时地报告备库延迟一个小时,然后很快又变回0


F:如果分发主库落后了,并且其本身也有已经追赶上它的备库,备库的延迟将显示为0,而事实上备库和源主库之间此时是有延迟的。




解决这些问题的办法是忽略这个值,并使用一些可以直接观察和衡量的方式来监控备库延迟,最好的解决办法是使用heartbeatrecord,这是一个在主库上每秒更新一次的时间戳,为了计算延迟,可以直接用备库当前的时间戳减去心跳记录的值,这个方法能够解决刚刚提到的所有问题,另外一个额外的好处是我们还可以通过时间戳知道备库当前的复制状况,包含在perconatoolkit里的pt-heartbeat脚本是复制心跳的最流行的一种实现。




心跳还有其他好处,记录在二进制日志中的心跳记录拥有许多用途,如:在一些很难解决的场景下可以用于灾难恢复。




pt-heartbeat介绍:


工作原理:


1,在主上创建一张heartbeat表,按照一定的时间频率更新该表的字段(把时间更新进去)。


2,从主库连接到从上检查复制的时间记录,和从库的当前系统时间进行比较,得出时间的差异。


使用方法:


shell>pt-heartbeat[OPTIONS][DSN]--update|--monitor|--check|--stop




在主库上创建一个测试库,测试库里创建好heartbeat表,然后开启守护进程来更新xiaoboluo.heartbeat表:




mysql>createdatabasexiaoboluo;


mysql>CREATETABLEheartbeat(


tsvarchar(26)NOTNULL,
server_idintunsignedNOTNULLPRIMARYKEY,
filevarchar(255)DEFAULTNULL,--SHOWMASTERSTATUS
positionbigintunsignedDEFAULTNULL,--SHOWMASTERSTATUS
relay_master_log_filevarchar(255)DEFAULTNULL,--SHOWSLAVESTATUS
exec_master_log_posbigintunsignedDEFAULTNULL--SHOWSLAVESTATUS
);




shell>pt-heartbeat-Dxiaoboluo--update-hlocalhost--user=username--password=password--daemonize




在主库上监控从的延迟情况:


shell>pt-heartbeat-Dxiaoboluo--monitor-hslave-server#一直执行,不退出pt-heartbeat-Dxiaoboluo--checkh=slave-server#执行一次就退出


常用参数:


注意:需要指定的参数至少有--stop,--update,--monitor,--check。其中--update,--monitor和--check是互斥的,--daemonize和--check也是互斥。




--ask-pass
隐式输入MySQL密码
--charset
字符集设置
--check
检查从的延迟,检查一次就退出,除非指定了--recurse会递归的检查所有的从服务器。
--check-read-only
如果从服务器开启了只读模式,该工具会跳过任何插入。
--create-table
在主上创建心跳监控的表,如果该表不存在。可以自己建立,建议存储引擎改成memory。通过更新该表知道主从延迟的差距。
CREATETABLEheartbeat(
tsvarchar(26)NOTNULL,
server_idintunsignedNOTNULLPRIMARYKEY,
filevarchar(255)DEFAULTNULL,--SHOWMASTERSTATUS
positionbigintunsignedDEFAULTNULL,--SHOWMASTERSTATUS
relay_master_log_filevarchar(255)DEFAULTNULL,--SHOWSLAVESTATUS
exec_master_log_posbigintunsignedDEFAULTNULL--SHOWSLAVESTATUS



);
heratbeat表一直在更改ts和position,而ts是我们检查复制延迟的关键。
--daemonize
执行时,放入到后台执行
--user
-u,连接数据库的帐号
--database
-D,连接数据库的名称
--host
-h,连接的数据库地址
--password
-p,连接数据库的密码
--port
-P,连接数据库的端口
--socket
-S,连接数据库的套接字文件
--file【--file=output.txt】
打印--monitor最新的记录到指定的文件,很好的防止满屏幕都是数据的烦恼。
--frames【--frames=1m,2m,3m】
在--monitor里输出的[]里的记录段,默认是1m,5m,15m。可以指定1个,如:--frames=1s,多个用逗号隔开。可用单位有秒(s)、分钟(m)、小时(h)、天(d)。
--interval
检查、更新的间隔时间。默认是见是1s。最小的单位是0.01s,最大精度为小数点后两位,因此0.015将调整至0.02。
--log
开启daemonized模式的所有日志将会被打印到制定的文件中。
--monitor
持续监控从的延迟情况。通过--interval指定的间隔时间,打印出从的延迟信息,通过--file则可以把这些信息打印到指定的文件。
--master-server-id
指定主的server_id,若没有指定则该工具会连到主上查找其server_id。
--print-master-server-id
在--monitor和--check模式下,指定该参数则打印出主的server_id。
--recurse
多级复制的检查深度。模式M-S-S...不是最后的一个从都需要开启log_slave_updates,这样才能检查到。
--recursion-method
指定复制检查的方式,默认为processlist,hosts。
--update
更新主上的心跳表。
--replace
使用--replace代替--update模式更新心跳表里的时间字段,这样的好处是不用管表里是否有行。
--stop
停止运行该工具(--daemonize),在/tmp/目录下创建一个“pt-heartbeat-sentinel”文件。后面想重新开启则需要把该临时文件删除,才能开启(--daemonize)。
--table
指定心跳表名,默认heartbeat。




测试环境:


Master192.168.0.68:3306


Slave192.168.0.38:3306




1,在主上运行:--daemonize表示守护进程,后台运行。


[root@xiaoboluo_192.168.0.68~]#pt-heartbeat--user=root--ask-pass--host=127.0.0.1--create-table-Dxiaoboluo--interval=1--update--replace--daemonize


Enterpassword:


[root@xiaoboluo_192.168.0.68~]#


[root@xiaoboluo_192.168.0.68~]#pgrep-flpt-heartbeat4156perl/usr/bin/pt-heartbeat-Dxiaoboluo--table=heartbeat--create-table--update-h127.0.0.1-uroot--ask-pass--daemonize


[root@xiaoboluo_192.168.0.68~]#




3.在主上运行监测复制延迟


[root@xiaoboluo_192.168.0.68~]#pt-heartbeat-Dxiaoboluo--table=heartbeat--monitor-h192.168.0.68


0.00s[0.00s,0.00s,0.00s]
0.00s[0.00s,0.00s,0.00s]
0.00s[0.00s,0.00s,0.00s]
0.00s[0.00s,0.00s,0.00s]
0.00s[0.00s,0.00s,0.00s]
0表示从没有延迟。[0.00s,0.00s,0.00s]表示1m,5m,15m的平均值。可以通过--frames去设置。





我们这里看见复制没有延迟,那么我们可以使用压力工具测试一下(这里因为是虚拟机做测试,性能比较差,所以直接使用存储过程循环插入数据做测试了)。在主库创建测试数据库sbtest,随便创建一个测试表:sbtest;


mysql>createdatabasesbtest;


QueryOK,1rowaffected(0.00sec)


mysql>createtablesbtest(idintunsignednotnullauto_incrementprimarykey,testvarchar(20));




创建存储过程:


mysql>delimiter$$


mysql>createproceduretest_sbtest(intest_timesint)

->begin

->set@x=0;

->ins:loop

->set@x=@x+1;

->if@x=test_timesthen

->leaveins;

->endif;

->insertintosbtest(test)values('test_sbtest');

->endloopins;

->end$$

QueryOK,0rowsaffected(0.01sec)


mysql>delimiter;

mysql>calltest_sbtest(100000);#这里调用存储过程循环写入10W次,会有一段时间


QueryOK,0rowsaffected(5min22.40sec)




再次检测复制延时:


[root@xiaoboluo_192.168.0.68~]#pt-heartbeat-Dxiaoboluo--table=heartbeat--monitor-h192.168.0.38


0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

0.00s[0.00s,0.00s,0.00s]

5.34s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

0.00s[0.09s,0.02s,0.01s]

1.07s[0.11s,0.02s,0.01s]


在上面的输出结果中红色字体部分可以看到延迟输出了




我们还可以使用--check监测一次就退出:


[root@xiaoboluo_192.168.0.68~]#pt-heartbeat-Dxiaoboluo--table=heartbeat--check-h192.168.0.38


0.00


[root@xiaoboluo_192.168.0.68~]#




注意:如果想把这个输出结果加入自动化监控,那么可以使用如下命令使监控输出写到文件,然后使用脚本定期过滤文件中的最大值作为预警即可:


pt-heartbeat-Dxiaoboluo--monitor-h192.168.0.38--log=/tmp/b.txt--daemonize#注意--log选项必须在有--daemonize参数的时候才会打印到文件中,且这个文件的路径最好在/tmp下,否则可能因为权限问题无法创建


#下面是定期过滤--log文件中最大值的脚本,加入监控调用即可:

#!/bin/bash

cat/tmp/b.txt>/tmp/b_tmp.txt

echo>/tmp/b.txt

max_time=`cat/tmp/b_tmp.txt|grep-v'^$'|awk'{print$1}'|sort-k1nr|head-1`

echo"$max_time"




2,如何关闭主上面执行的后台进程。可以用参数--stop去关闭:


[root@xiaoboluo_192.168.0.68~]#pt-heartbeat--stop#注意,这个命令会把所有的pt-heartbeat进程都停掉


Successfullycreatedfile/tmp/pt-heartbeat-sentinel


[root@xiaoboluo_192.168.0.68~]#


这样就把在主上开启的进程杀掉了,后续要继续开启后台进行的话,需要把/tmp/pt-heartbeat-sentinel文件删除,否则启动不了