共计 2590 个字符,预计需要花费 7 分钟才能阅读完成。
行业资讯
数据库
当 master down 掉后 pt-heartbeat 不断重试会导致内存缓慢增长的原因及解决办法
当 master down 掉后,pt-heartbeat 不断重试会导致内存缓慢增长的原因及解决办法,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
最近同事反映,在使用 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-heartbeatroot 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-tableroot 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 的版本有关。
很好奇,失败的连接如何导致内存的不断增长?
看完上述内容,你们掌握当 master down 掉后,pt-heartbeat 不断重试会导致内存缓慢增长的原因及解决办法的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注丸趣 TV 行业资讯频道,感谢各位的阅读!