对于SQL,我们一般都会讲SQL审计,SQL优化,很少讲SQL监控。确实,SQL很难监控,因为在一个复杂的系统中,每天的SQL执行量高达千万级,甚至数百亿级,不同的SQL执行量可能高达数万级或数十万。如果动态生成大量SQL,或者不使用绑定变量,几分钟内可能会执行上万条不同的SQL。在这样的情况下,如果要开发一个通用的SQL监控产品,难度是很大的。当然,如果我们的业务系统比较稳定,需要监控的SQL数量也比较稳定,那么针对这些SQL进行针对性的监控就比较容易实现。事实上,对于大多数企业来说,我们需要监控的数据库系统有成百上千个,而且业务系统是不断变化的。在这种环境下,确实很难实现通用的SQL监控。对于DBA来说,对于SQL语句的监控也会有一定的要求,也会掌握一些SQL语句的监控和分析技巧。对于Oracle数据库的DBA来说,我们非常习惯于通过AWR上报的TOPSQL相关内容来分析SQL的运行状态,发现有问题的SQL。但是,这种分析只能算是SQL优化,不能算是SQL监控。今天我们就来讨论SQL监控的问题。随着硬件、云平台、数据库技术和应用架构的不断优化和演进,完全由硬件资源或数据库配置导致的数据库问题所占比例相对较小,而由于SQL运行和运行导致的问题所占比例越来越大维护。SQL的监控需求一直存在,需求的种类也是五花八门。前段时间有客户问,想知道某段时间内某条随机SQL的具体执行次数,问我们D-SMART是否支持。还有客户问我D-SMART是否支持跟踪任意SQL的执行计划变化,发现问题及时报警。SQL监控的目的其实还是为了及时发现系统中可能存在的风险。我和我的第一个朋友聊起他需要如此精确监控的目的,他说不出为什么。其实从应用的角度来说最好能满足这个需求。在应用系统的模块中通过hooks统计的成本是最低的,而从数据库做成本可能太高了。如果要从数据库的角度去统计,它的准确性会大大降低,因为数据库内存中保存的SQL统计数据是不完整的,所以我们采样的时候就会出现误差。当某个SQL在一定时间内没有被执行时,很可能会从内存统计缓冲区中清除,下次再次出现时,可能会从头开始统计。目前我们的TOPSQL收集工作也是每5分钟进行一次,将这段时间比较活跃的SQL统计一次。因为大系统中的SQL数量可能会非常多,为了避免生产系统负载过大,这种采集也必须是轻量级的,只采集一些非常重要的TOPSQL详细信息。至于第二个需求,如果我们要跟踪全量SQL的执行计划,肯定是不现实的。如果系统中有几万条SQL,几十万条执行计划,收集一次的成本是巨大的。对于一些高并发、业务对SQL执行延迟的稳定性要求高的系统,是难以忍受的。Oracle数据库的SQL语句都存储在共享内存的CURSOR结构中,但是很多开源和国产数据库并没有采用全局共享CURSOR的方式,CURSOR只在会话内部共享。因此,收集SQL语句和执行计划的接口并不完善,有些数据库甚至需要启用一些特殊的跟踪功能才能实现。针对不同的数据库产品,我们需要采用不同的方式来收集TOPSQL,所以SQL监控的实现还是需要精心设计的。还有一点,我们SQL监控的目的并不是SQL监控本身。SQL监控的目标是防止SQL出现异常,从而导致数据库系统出现问题。所以,我们不能把SQL监控当成最初的目标,而是把SQL监控当成一种手段和方法。因此,在一个系统中,监控某个SQL在某个时间段内的精确执行次数,在大多数场景下是没有意义的。我们只需要知道某些可能影响系统的SQL语句的大概执行次数,以及每次执行的平均执行次数即可。执行次数和开销的开销和历史波动足以支撑我们需要的运维分析场景。但是,如果某条SQL语句的执行计划发生了变化,如果它的执行成本没有增加,对数据库的稳定运行影响不大,那么我们就不需要实时发现这种变化,只要因为定期审计有变化。发现和分析潜在的风险就足够了。但是由于执行计划的改变,导致系统负载过高,系统性能下降,我们也可以从其他方面观察。我们可以通过使用数据库可观察性的其他一些方面来发现此类问题。比如我们可以很容易的通过整个系统逻辑读/物理的突然增加,CPU使用率的增加,活跃会话数的增加来观察,也可以发现监控成本相对较低的可观察性指标因为SQL执行计划改变了。可以通过分析定位到坏SQL导致的问题,很快发现是坏SQL执行计划导致的问题。那么我们也可以解决这个问题。例如在D-SMART中,通过关键SQL的平均逻辑读突发和每秒逻辑读超出正常水平等两种方法来发现相关问题。我们来看看D-SMART是如何分析这个关键SQL的平均逻辑读突然增加告警的问题。从SQL的历史分析来看,确实存在平均逻辑读突变。我们再来看看SQL执行计划,是否有多个执行计划。从分析来看,确实存在两种不同的子游标,而且其中一种游标的执行成本明显大于另一种。正是因为这个问题,才出现了这个告警。这种方法针对的是关键SQL,即系统中对应用可用性或SLA有关键影响的SQL,我们可以在每个采样周期对其进行监控。因为系统中的关键SQL数量不是很多,所以这种专项监控的成本并不高。而如果问题不是关键SQL,而是任何一个SQL,突然因为统计信息不准确或者表数据量发生变化,或者系统变更后应用出现BUG,导致执行计划发生变化,进而导致系统资源不足,导致系统资源(内存、CPU、IO等)不足导致关键SQL导致的性能问题。这种情况也很常见。如果这个SQL的问题还没有触发系统资源不足,导致核心业务失败,那么这个问题不一定需要马上抓到处理。你只需要在定期的SQL审计中(比如每周一次)发现这个问题,就可以彻底解决。如果比较严重的话,可能会导致系统故障,所以我们还是要及早发现此类问题。在D-SMART中,我们针对逻辑读突发、物理读突发、R队列突发、活跃会话数突发,同一条SQL的并发执行达到一定的阈值。如果时间过长,如果对系统影响很大,大概率会同时执行多条SQL)等,会产生告警。并且在这些告警中,可以有执行计划变化的诊断路径,可以用来追根溯源。这样就采用了迂回策略,从一方面解决了此类问题的预警问题。
