一、故障时间:
发生时间:2015.11.17 凌晨2:10点左右
解决时间:2015.11.17 早上8:40分左右
二、故障解决人员:
XXX
三、故障现象:
XXX WEB、系统无法登陆,通过堡垒机连接系统完全无响应,数据库主库大量的查询被阻塞,插入更新语句无法执行
四、故障排查:
首先通过堡垒机登陆XXX系统,查看状态,但是因系统无响应,只有联系idc机房人员进行手动重启系统。同时登陆平台数据库主库系统查看MySQL进程状态,显示出大量的表需要等待XXX_order表的tableflush状态完成(P-2所示)。大约10分钟后XXX系统启动完成,登陆后查看系统状态,各个服务都运行良好。只是一直收到监控系统的报警:系统进程在不断增加。应该可以很清楚的知道是因为数据库的XXX_order和XXX_task_queue表需要完成flushtable,而长时间没有完成导致的。
五、故障解决:
目前的主要问题就在如何解决阻塞的问题,当时通过查看系统进程大概有3000多个Waitingfor table flush的SQL,全部是XXX库(XXX_order)相关的表(P-2所示)。手工kill掉一些select类型的SQL并不能起作用,这时候应该找到产生阻塞的具体SQL才对。之前对数据库系统做了一个监控系统进程状态的脚本,打开日志文件,查看里面具体的SQL(P-3所示)找到执行时间最长的那个,kill掉对应的SQL ID应该就释放了阻塞。大量的Waiting for table flush 状态消失,系统恢复正常。
P-1
P-2
P-3
六、故障原因:
因一个性能较差通过手工执行的SQL在通过堡垒机进行查询时手工终止(ctrl+c)但是在MySQL实例已经开始了Copying数据到tmp表中,并没有结束掉,还是一直在数据库中执行。查询执行时间长达10多个个小时。同时备份的脚本启动,开始出现阻塞的时间在凌晨2点钟左右,那个时间正好是数据库备份开始执行的时间,mysqldump会发出flushtables的动作,因为SQL执行的慢,导致无法完成mysqldump需要对XXX_order和XXX_task_queue表的tableflush动作导致阻塞了其他查询,插入更新等对XXX_order和XXX_task_queue表的请求的堆积,同时XXX系统相关的计划任务很多是每一分钟执行一次,造成XXX的计划任务不能及时执行完成,系统进程数量陡增(P-4所示),造成XXX系统崩溃。
P-4
七、问题解决方案
1. 监控MySQL Processlist 的xxx_select账号执行的时间,如果超过1800秒就将其线程进行kill掉终止执行。
2. 通过Nagios监控MySQL Processlist中出现Waitingfor table flush、Waitingfor table metadata lock和flushtable with read lock的数量,如果超过5个就要发出报警,运维人员介入处理,根据日志来查找具体原因
3. 搭建一个新的专门处理查询任务的从库,此从库不影响业务
八、故障后的反思:
通过这次故障应该吸取教训:
1. 对数据库的任何操作都要谨慎、敬畏,因为数据是企业的生命。当进行增删改查的时候就要知道造成的后果是什么?操作前做好充分的测试,再去线上进行执行,比如看SQL的执行计划是否是最优化的性能、是否会造成数据的不一致问题,主从是否会出现中断等。不会对现有的业务造成影响,否则就不应该进行线上操作,切记!
2. 运维在系统监控这边执行的不是很到位,需要自我反省。通常在手机接收到报警的时候第一时间进行处理(凌晨两点左右),当时在看到手机报警的时候没有看清是系统没有响应了(熟睡中醒来看什么都迷糊)手机登录管理系统能ping的通XXX系统的网络,结合报警类型来看只是暂时的无响应,但当收到大量报警时候,发现是比较严重的问题了,着手处理问题的时间在早上7点半左右,这期间有充足的时间去处理。并且监控系统在问题发生之前就已经预警了,并没有引起重视!才造成后续更严重的问题!对于以后产生环境的报警应该加以重视,不能掉以轻心,将问题在萌芽状态就要及时发现并处理!
3. 对系统运行时状态的即时转存储对于解决问题有很大的帮助,所以应该考虑对系统状态做快照处理保存,以便查找问题出现的根本原因。