近年来同事反映,在运pt-heartbeat监控主从复制延迟的经过中,如果master
down掉了,则pt-heartbeat则会连失败,但会随地重试。
重试本无可厚非,毕竟从使用者的角度来说,希望pt-heartbeat能不断重试,直到再次连接达数据库。但是,他们发现,不断的重试会带动内存的慢增长。
重现
环境:
pt-heartbeat v2.2.19,MySQL社区版 v5.6.31,Perl v5.10.1,RHEL
6.7,内存500M
为避免数据库启停对pt-heartbeat内存使用率的影响,故MySQL和pt-heartbeat分别运行在不同的主机上。
运行pt-heartbeat
# pt-heartbeat –update -h 192.168.244.10 -u monitor -p monitor123 -D
test –create-table
督查pt-heartbeat的内存使用率
获取pid
# ps -ef |grep pt-heartbeat
root 1505 1471 0 19:13 pts/0 00:00:08 perl /usr/local/bin/pt-heartbeat --update -h 192.168.244.10 -u monitor -p monitor123 -D test --create-table
root 1563 1545 2 19:50 pts/3 00:00:00 grep pt-heartbeat
查阅该过程的内存使用率
# top -p 1505
运行了0:15.00(TIME+列),MEM一直平稳在3.3%
临时关闭数据库
# service mysqld stop
刚才之pt-heartbeat命令不断输出以下信息
同一CPU时间晚,MEM增长至4.4%,
增长了1%,考虑到内存500M,该过程的内存占用多了5M,虽然非是群,但考虑到过程的内存增加并不曾停歇的意思,这个状况还是要引注意的。
以,通过pmap命令,发现,0000000001331000地址的RSS和Dirry也会见增进,增长之速率是4k/s
新生研究pt-heartbeat的源码,才意识代码有点bug
my $tries = 2;
while ( !$dbh && $tries-- ) {
PTDEBUG && _d($cxn_string, ' ', $user, ' ', $pass,
join(', ', map { "$_=>$defaults->{$_}" } keys %$defaults ));
$dbh = eval { DBI->connect($cxn_string, $user, $pass, $defaults) };
if ( !$dbh && $EVAL_ERROR ) {
if ( $EVAL_ERROR =~ m/locate DBD\/mysql/i ) {
die "Cannot connect to MySQL because the Perl DBD::mysql module is "
. "not installed or not found. Run 'perl -MDBD::mysql' to see "
. "the directories that Perl searches for DBD::mysql. If "
. "DBD::mysql is not installed, try:\n"
. " Debian/Ubuntu apt-get install libdbd-mysql-perl\n"
. " RHEL/CentOS yum install perl-DBD-MySQL\n"
. " OpenSolaris pgk install pkg:/SUNWapu13dbd-mysql\n";
}
elsif ( $EVAL_ERROR =~ m/not a compiled character set|character set utf8/ ) {
PTDEBUG && _d('Going to try again without utf8 support');
delete $defaults->{mysql_enable_utf8};
}
if ( !$tries ) {
die $EVAL_ERROR;
}
}
}
上述代码摘自get_dbh函数,用于获取数据库的连续,如果获失败,则重试1不好,然后经die函数抛大退出。
可,通过安装如下断点,发现当$tries为0时,if函数里面的PTDEBUG &&
_d(“$EVAL_ERROR”)语句能行,但die函数就是没弃来老,并脱离脚本
PTDEBUG && _d($tries);
if ( !$tries ) {
PTDEBUG && _d("$EVAL_ERROR");
die $EVAL_ERROR; }
新兴,将上述代码的最后一个if函数修改如下:
if ( !$tries ) {
die "test:$EVAL_ERROR";
}
重复测试
启航数据库
# service mysqld start
执行pt-heartbeat命令
# pt-heartbeat –update -h 192.168.244.10 -u monitor -p monitor123 -D
test –create-table
停下数据库
# service mysqld stop
刚刚实践之pt-heartbeat命令异常退出
“test:”就是在的测试字符。
结论
死奇怪,只是一味的die
$EVAL_ERROR不会见扔来老,并退脚本,但修改后底die
“test:$EVAL_ERROR”却会脱离脚本。
万分明朗,这实在是单bug,不明白凡是不是同perl的本子有关。
那个奇异,失败的连如何造成内存的缕缕增强?
最终,给percona官方提了只bug
https://bugs.launchpad.net/percona-toolkit/+bug/1629164