如何使用MySQL MHA源代码进行监控检查
本篇文章给大家分享的是有关如何使用MySQL MHA源代码进行监控检查,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
一、前言
在研究的同时,把MHA的源代码也翻阅了一遍,现在准备把MHA一些重要内容梳理一下,既然是高可用工具,那么健康检测是一个基础工作,只有正确检测了数据库的故障,才能进行数据库的切换;而MHA的布局亦如此:
二、MHA健康检查核心调用函数链
注意我这里的函数调用链的规则是文件名|方法名,方法名中的或者表示的是,通过读取配置文件,执行其中的一个函数
MasterMonitor.pm|MHA::MasterMonitor::main()
->MasterMonitor.pm|MHA::MasterMonitor::wait_until_master_is_dead()
->MasterMonitor.pm|MHA::MasterMonitor::wait_until_master_is_unreachable()
->HealthCheck.pm|MHA::HealthCheck::wait_until_unreachable()
->HealthCheck.pm|MHA::HealthCheck::ping_select(或者)
->HealthCheck.pm|MHA::HealthCheck::ping_insert(或者)
->HealthCheck.pm|MHA::HealthCheck::ping_connect(或者)
三、代码分析
我们主要看HealthCheck.pm|MHA::HealthCheck::wait_until_unreachable的实现
1) 该函数通过一个死循环,检测4次,每次sleep ping_interval秒(这个值在配置文件指定,参数是ping_interval),持续四次失败,就认为数据已经宕机
2)如果有二路检测脚本,需要二路检测脚本检测主库宕机,才是真正的宕机,否则只是推出死循环,结束检测,不切换
3)这里的GETLOCK(姑且说是分布式锁)就是用来保护数据库的访问,防止脚本多次启动的
4)该函数调用了三种经检测方法,如下:
PING_TYPE_CONNECT(ping_select),PING_TYPE_INSERT(ping_insert),PING_TYPE_SELECT(ping select),但是哪种最好呢,我建议是PING_TYPE_CONNECT,实际上PING_TYPE_CONNECT调用了ping_select的方法,比PING_TYPE_CONNECT更具有可靠性
#mainfunction#返回1,表示数据库有问题,但是不会切换;0表示数据库有问题,会切换(这里同时还会返回ssh连接状态,方便确认是网络问题,还是数据库问题)subwait_until_unreachable($){my$self=shift;my$log=$self->{logger};my$ssh_reachable=2;my$error_count=0;my$master_is_down=0;eval{while(1){$self->{_tstart}=[gettimeofday];if($self->{_need_reconnect}){#测试连接,连接正确返回0,否则返回1##这里有分布式GetLOCK,如果有别的会话,获取了分布式锁失败,也算连接不成功my($rc,$mysql_err)=$self->connect(undef,undef,undef,undef,undef,$error_count);if($rc){#排除权限错误if($mysql_err){if(#在这里并不是不能访问,可能只是权限错误grep($_==$mysql_err,@MHA::ManagerConst::ALIVE_ERROR_CODES)>0){$log->info("GotMySQLerror$mysql_err,butthisisnotaMySQLcrash.Continuehealthcheck..");#sleep一段时间$self->sleep_until();#好吧,如果是权限错误的话,就一直在这里循环了,那么检测一致认为mysql正常,打印权限日志就行next;}}$error_count++;$log->warning("Connectionfailed$error_counttime(s)..");#处理失败,更新status_file为20:PING_FAILING$self->handle_failing();#超过四次就跳出这个循环了if($error_count>=4){#返回1表示ssh可以可以到达,0表示ssh不能到达$ssh_reachable=$self->is_ssh_reachable();#返回为1表示数据库主库已经down,0则没有down$master_is_down=1if($self->is_secondary_down());#退出循环,lastlastif($master_is_down);$error_count=0;}$self->sleep_until();next;}#connectionok$self->{_need_reconnect}=0;$log->info("Ping($self->{ping_type})succeeded,waitinguntilMySQLdoesn'trespond..");}#释放连接,如果只是类型为PING_TYPE_CONNECT$self->disconnect_if()if($self->{ping_type}eq$MHA::ManagerConst::PING_TYPE_CONNECT);#Parentprocessforksonechildprocess.Thechildprocessqueries#fromMySQLevery<interval>seconds.Thechildprocessmayhangon#executingqueries.#DBD::mysql4.022orearlierdoesnothaveanoptiontoset#readtimeout,executingqueriesmighttakeforever.Toavoidthis,#theparentprocesskillsthechildprocessifitwon'texitwithin#<interval>seconds.my$child_exit_code;eval{if($self->{ping_type}eq$MHA::ManagerConst::PING_TYPE_CONNECT){$child_exit_code=$self->fork_exec(sub{$self->ping_connect()},"MySQLPing($self->{ping_type})");}elsif($self->{ping_type}eq$MHA::ManagerConst::PING_TYPE_SELECT){$child_exit_code=$self->fork_exec(sub{$self->ping_select()},"MySQLPing($self->{ping_type})");}elsif($self->{ping_type}eq$MHA::ManagerConst::PING_TYPE_INSERT){$child_exit_code=$self->fork_exec(sub{$self->ping_insert()},"MySQLPing($self->{ping_type})");}else{die"Notsupportedping_type!\n";}};if($@){my$msg="Unexpectederrorheppenedwhenpinging!$@";$log->error($msg);undef$@;$child_exit_code=1;}if($child_exit_code==0){#pingok#ping是成功的话,则更新状态,然后将$error_count=0(持续累积4次,那就是连接有问题)$self->update_status_ok();if($error_count>0){$error_count=0;}#handle_failing启用了二路检测以及ssh_check这时候没结束需要kill掉$self->kill_sec_check();$self->kill_ssh_check();}#存在其他分布式监控elsif($child_exit_code==2){$self->{_already_monitored}=1;croak;}else{#failedonfork_exec$error_count++;$self->{_need_reconnect}=1;$self->handle_failing();}$self->sleep_until();}$log->warning("Masterisnotreachablefromhealthchecker!");};if($@){my$msg="Goterrorwhenmonitoringmaster:$@";$log->warning($msg);undef$@;return2if($self->{_already_monitored});return1;}#$master_is_down=0,返回1return1unless($master_is_down);#0,$ssh_reachable返回1表示ssh可以可以到达,0表示ssh不能到达return(0,$ssh_reachable);}1;三种检测机制函数#这个ping_connect正常返回0,错误返回1或者2,1是连接存在问题,2是获取锁失败#改函数调用了ping_selectsubping_connect($){my$self=shift;my$log=$self->{logger};my$dbh;my$rc=1;my$max_retries=2;eval{my$ping_start=[gettimeofday];#连接max_retries次,如果有错误,则退出while(!$self->{dbh}&&$max_retries--){eval{$rc=$self->connect(1,$self->{interval},0,0,1);};if(!$self->{dbh}&&$@){die$@if(!$max_retries);}}#ping_select()正常返回为0,错误返回为1$rc=$self->ping_select();#Toholdadvisorylockforsomeperiodsoftime#获取锁可能需要一定时间,所以在释放连接之前,需要等待一点时间$self->sleep_until($ping_start,$self->{interval}-1.5);$self->disconnect_if();};if($@){my$msg="GoterroronMySQLconnectping:$@";undef$@;$msg.=$DBI::errif($DBI::err);$msg.="($DBI::errstr)"if($DBI::errstr);$log->warning($msg)if($log);$rc=1;}return2if($self->{_already_monitored});return$rc;}#语句SELECT1AsValue,正常返回0,错误返回为1subping_select($){my$self=shift;my$log=$self->{logger};my$dbh=$self->{dbh};my($query,$sth,$href);eval{$dbh->{RaiseError}=1;$sth=$dbh->prepare("SELECT1AsValue");$sth->execute();$href=$sth->fetchrow_hashref;if(!defined($href)||!defined($href->{Value})||$href->{Value}!=1){die;}};if($@){my$msg="GoterroronMySQLselectping:";undef$@;$msg.=$DBI::errif($DBI::err);$msg.="($DBI::errstr)"if($DBI::errstr);$log->warning($msg)if($log);return1;}return0;}#正常返回0,错误返回1,有个疑问,这里见得数据库表貌似没有清理吧subping_insert($){my$self=shift;my$log=$self->{logger};my$dbh=$self->{dbh};my($query,$sth,$href);eval{$dbh->{RaiseError}=1;$dbh->do("CREATEDATABASEIFNOTEXISTSinfra");$dbh->do("CREATETABLEIFNOTEXISTSinfra.chk_masterha(`key`tinyintNOTNULLprimarykey,`val`int(10)unsignedNOTNULLDEFAULT'0')engine=MyISAM");$dbh->do("INSERTINTOinfra.chk_masterhavalues(1,unix_timestamp())ONDUPLICATEKEYUPDATEval=unix_timestamp()");};if($@){my$msg="GoterroronMySQLinsertping:";undef$@;$msg.=$DBI::errif($DBI::err);$msg.="($DBI::errstr)"if($DBI::errstr);$log->warning($msg)if($log);return1;}return0;}
四、总结
1)数据库MHA的健康检查,最终调用的ping_select,ping_insert,ping_connect的一种,检测的时间由ping_interval控制,其中ping_connect调用了ping_select
2)MHA最好配置二路检测,否则只是MHA主节点从自身ssh去检测主库是否正常,在MHA管理节点与主库网络存在问题的时候,有可能会发生误切换
3)注意:这里只列出了核心函数,其实在程序启动的时候,还有一些启动情况检查,基本是主库是否可连接,配置是否正确,从库是否正常等等
以上就是如何使用MySQL MHA源代码进行监控检查,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。