MySQL实践——历史问题诊断和现场故障分析

概要

在实际的性能调优问题分析和验证案例中,按照现场的“真实”程度,简单来说,可以把问题排查场景分为两类。

(1)历史问题排查

历史问题排查,指对于无法重现或者避免影响生产环境的问题,在很多情况下,DBA只能依赖性能监控工具、日志等信息进行分析和排查。此时是否有足够的信息以供诊断和分析就显得非常重要了。如何模拟生产环境预估高压力情况下系统的表现,一直是DBA甚至整个运维和业务系统部门的难题,通过tcpcopy(将业务压力导入线下测试)、数据建模(建立各个模块和数据的压力匹配模型)、全链路压测(通过建立影子表在真实的生产环境中直接测试,通过细粒度监控和精细控制,在可能影响生产环境时及时停止测试),三次性能压测评估系统的迭代,各大互联网公司才能基本比较精确地预估线上压力的影响。

(2)在线问题分析

在问题可重现或者保留了问题现场的情况下,除了需要普通的监控工具,更需要在线实时分析工具。通过更细粒度的分析和对故障信息的收集,能辅助DBA做出更加准确的判断和对故障原因的假设。

1. 历史问题排查

(1)历史问题排查,需要使用性能监控工具

性能监控需要有专门的工具进行数据采集、整理和展示。本书采用的性能监控工具是Prometheus和Grafana。首先,性能监控工具会通过客户端或者直接连接数据库、数据库主机采集相关的指标并存入本地数据库中;然后,针对这些数据会根据展现的需要分门别类地进行汇总、计算(比如采集的数据是questions,就需要获得两次采集的数据的差值除以两次采集的时间间隔以显示QPS值);最后,通过页面的形式以散点图、火焰图、柱状图等展现出来。为了避免采集程序本身给数据库造成额外的压力,性能监控工具一般间隔30~300s采集一次数据。

(2)历史问题排查,需要参考日志信息

需要参考的日志信息包括服务器日志信息(包括硬件日志、RAID卡日志等)、操作系统日志信息(包括message、dmesg日志等)、MySQL数据库日志信息(包括错误日志、慢查询日志、二进制日志、普通日志)等。例如:线上某些数据出现了异常,通过查询二进制日志就可以知道什么时间哪些SQL语句修改了这些数据;数据库SQL语句执行报错,如果在MySQL错误日志中没有查看到相关信息,则也可以通过查看慢查询日志来诊断,如果看到该条SQL语句的执行时间很长,则可能是由于应用程序使用的连接池本身的超时功能断开连接导致的报错。

2 在线问题分析

(1)在线问题分析,可以利用在线细粒度监控工具来获得相关信息

在线细粒度监控工具主要用于现场分析环境,及时有效地评估性能瓶颈或者故障原因。top、dstat、vmstat等系统层面的工具和innotop等数据库层面的工具都属于这类工具。在故障重现时通过系统、数据库的相关实时分析工具来了解运行情况,诊断性能问题。

(2)在线问题分析,可以利用故障触发采集工具来采集故障出现时现场的相关环境情况

在很多情况下,故障出现的时间非常短,触发也是随机出现的,无法在故障出现时及时捕获有用的信息。Percona的pt-stalk就是专门为MySQL准备的在问题出现时采集堆栈、I/O、processlist等情况的工具。关于具体的pt-stalk命令选项、输出结果解读等内容,请参考Percona-Toolkit常用工具详解。当前版本的Percona工具跟performance_schema结合还没有那么深入,如果能加上performance_schema来帮助诊断问题就更完美了。

3 故障复现排查

我们可以从系统日志、性能监控数据上发现一些线索,猜测大致发生了什么问题,判断是什么原因导致的。但是如果不能复现故障,这个猜测和判断只能是假设,而且给出的解决方案能不能100%解决问题,避免以后出现类似的故障,也是无法确定的。所以,故障复现是彻底解决问题的关键步骤。

这里说的“故障复现”指的是开发人员或者DBA本身发现数据库问题后,在有一定的假设前提下尝试复现这个故障,确定故障发生的原因。开发人员反映SQL语句执行慢、数据库崩溃宕机、性能监控数据显示一个异常的尖峰等都属于这类故障。

要想使故障重现,需要DBA结合使用监控数据和日志等,根据经验和故障现象推理故障原因,并按照假设的故障原因去重现故障;通过重复的验证测试,找到必然重现故障和必然不重现故障的区别,验证假设是否成立。很多时候,由于经验不足和没有关注到部分故障现象细节,需要不断地调整对故障原因的假设。已知故障复现的关键点在于:

(1)能准确地复现故障当时的场景

如果一个故障无法重现,那么即使使用监控工具能大致判断出出错的原因,也仍然无法保证下次不会出现同样的故障。

(2)对故障现象的把控,即问题的定义

对于故障发生的时间、MySQL的报错信息、系统日志中的错误信息、硬件日志及报错信息,以及监控系统和MySQL在故障期间的异常情况,在故障发生前开发人员或者运维人员做过的发布、修改等操作,都是DBA需要了解和整理的。

另外需要注意的是,当一个故障发生时,你需要关注你看到的到底是故障的结果还是故障的原因。

(3)对故障原因的假设

对故障原因的假设,更多的基于DBA对MySQL运行机制原理的了解和经验。在Oracle中有非常标准的和科学的故障诊断机制,只需要按照对应的方法一步一步地排查分析就基本能找到问题的原因。比如,SQL语句执行慢,就可以通过v$session来查看这个会话到底堵塞在什么地方,是执行计划不对、I/O太多,还是被另一条SQL语句锁住了,如果是被SQL语句锁住了,那到底是谁锁住了,甚至可以生成锁的依赖链表。

幸运的是,MySQL合并到Oracle以后,MySQL推出了performance_schema,用于采集和统计MySQL在会话、事务、SQL以及各个阶段的消耗,虽然还没有Oracle那么详细和精确,但是让MySQL在诊断方面从无到有提升了一个量级。

另外,这里有一个小经验分享一下。只要你仔细观察,就会发现很多故障都是由于在故障现象出现之前所做的操作导致的。理由很简单,数据库上线后正常运行一般会有较长时间的稳定期,如果突然出现SQL语句执行慢、监控数据出现尖峰等情况,通过都是由于前一天应用发布了新的功能、早上运营人员做了专门的活动、前一天晚上做了一个参数变更、网络部门加了专门的安全策略等导致的。

(4)对假设的验证

这一步依据故障原因和故障分析的结论,找到解决方案,在类似的测试环境中验证是否能避免故障发生,从而避免未来同样的故障在生产环境中继续发生,也证明第(3)步对故障原因的假设是正确的。比如,我们假设PHP短连接下网络的TIME_WAIT状态的Socket太多是由于网络参数导致的,那么就需要在修改对应的网络参数以后,模拟真实的场景进行验证测试。

如果在修改网络参数以后能解决这个问题,那么基本就可以确定之前的假设是正确的(如果之前的假设范围太大,比如通过替换整个监控采集客户端来解决系统卡顿的问题,那么可能还需要对每个采集项进行细化验证);如果仍然没有解决问题,那么就需要回到“对故障原因的假设”上,进一步扩大或者修改假设的原因。

小结

本章简单总结了日常故障排查的方法和思路,按照故障已经发生和在故障现场诊断、分析来区分,介绍了一些需要注意的要点。本章最后对故障重现和现场分析进行了详细介绍,包括故障复现排查时的4个关键点。同学们在具体分析和解决问题时,一定要注意问题的定义,不断追问导致故障的问题到底是什么,持续逼近问题的真相。

你可能感兴趣的:(MySQL编程,mysql,数据库,MySQL故障分析,数据库故障分析)