前几天我发文章谈到十分糟糕的系统的优化要十分谨慎,这些天不少朋友和我交流过这个问题,对我所说的排队效应的问题能够理解,但是以他们以往的经验,似乎只要去做了优化,无论如何都是有效的,并没有遇到过我所说的问题。
要回答这个问题并不容易,因为不同的应用场景,不同的应用系统之间存在的差异较大。另外一点就是目前绝大多数需要优化的系统,系统比较慢,但是各种服务器资源还较为充足。在这种情况下,哪怕某个堵点被疏通了,新的堵点还没有耗尽资源,或者形成更严重的拥堵,那么哪怕系统中的某些模块稍微慢一点,使用者可能也是无感的。
对于一些复杂的、服务器负载极高、多种资源都在高位运行的系统中做优化,就完全不同了。十五年前我写《Oracle优化日记》的时候的那个案例就是如此,那本书出版后,也有一些朋友质疑我说的项目的真实性,这个优化项目有太多的限定条件了,因此想做一些简单的优化,从而达到目标都变得不可能,必须采用全面优化的“组合拳”,并且在每个优化步骤上都要精心设计,不能乱序。实际上这是一个绝对真实的优化项目,也只有这样的优化项目,才需要专业的优化团队去实施。而日常大家遇到的优化可能只需要做些局部的优化就可以了。
实际上在我做优化的这二十多年时间里,近一半的优化项目确实只要加几个索引,优化几条SQL就可以搞定了。另外一方面,我确实也遇到过很多需要精心设计优化方案的优化项目。
十年前,我们给一个烟草公司做优化,他们的系统2年后就要升级换代,优化的目的就是让系统能够撑过这两年。这套系统平时没什么问题,就是月底或者临时上报数据时需要做的大量的统计操作动不动要几个小时才能完成,让业务人员加班加点干有时候都要忙到半夜。为了解决这个问题,我们已经把操作系统和存储的性能压榨干了。于是最后只能动了存储读写缓冲区的主意。这套老旧的EMC存储的读写缓冲区默认是倾向于写操作的,因此写缓冲占比更大。因为业务特点是写操作是分散的,读操作是集中的,因此我们将读写缓冲区的比例做了调整,调整为读写均衡的模式。
前几天我所说的那个优化项目也为这种场景提供了一个十分好的样例。这几天系统已经进入了月底结算的业务高峰期,我之前提出在业务高峰期前打一套“组合拳”,不过因为开发商无法全面完成这些工作,只完成了一些他们擅长的优化工作-建索引,在系统中临时添加了数十条索引。确实添加了索引后,一些SQL从TOP SQL中消失了。不过这个从周一开始的业务高峰期却险象环生了。
周一的时候业务负载已经开始增加,不过还没达到极限,前几天的优化效果还是挺明显的,r队列(Unix LOAD)高峰在500左右,对于一个128核,256线程的老8路服务器来说,还能够承受。业务单位也反馈业务模块的响应时间虽然慢,但是没有出现不可用的情况,凑合能够接受。
经受住第一天的考验后,大家也没有掉以轻心,开发商连夜对当天发现的部分TOP SQL做了加索引的优化工作。
当大家都觉得前阶段优化有效,准备庆祝的时候,第二天风云突变。上午承载较多业务的1号数据库服务器节点的r队列突然飙升,大家可以看到上面的图中与前一天比较的差异。优化组经过分析发现大多数CPU消耗来自于一条做动态采样的SQL,因为某张表缺失统计数据,导致大量的动态采样。这条SQL以往的执行频率没有那么高,因此也没有被开发商排在优先优化的清单里。中午趁着午休把表做了表分析后,大家还觉得不踏实。于是建议停掉一些非关键业务,确保下午的运行安全。大家可以看到,下午1号节点的r队列比前一日有了明显好转。
不过下午三点多以后,以前比较让人省心的节点2突然又出问题了,R队列飙升到2000以上。系统变得极为缓慢。通过D-SMART分析发现SYS%的CPU很高,接近90%,USR%只有10%左右。从等待事件上看,library cache的等待较多。有些DBA就把问题聚焦到硬解析过大的问题上了。确实从D-SMART上可以看到平均每秒硬解析数量超过100,有时甚至好过200。不过我认为硬解析并无问题,因为硬解析消耗的CPU只有不到5%(non parse cpu%),并且并发执行量仅为每秒4000左右。
通过分析发现,Library cache闩锁等待严重的主要原因是有大量的并发执行的SQL语句。单条SQL语句居然高达900+并发。经过检查发现,这些语句都是DDL语句。当系统负载较小时,这些DDL语句的执行效率很高,因此不会形成阻塞。不过从分析的结果来看,我们排除了硬解析的问题,也算是虚惊一场,否则要解决硬解析问题可就不是一天两天可以搞定的事情了。
惊心动魄的一天不但让开发商和优化项目组筋疲力尽,用户也痛苦不堪。很多用户连夜加班到下半夜1点多钟,因为第二天监控人员从系统负载上看到,到了下半夜3点左右,依然有数百个用户登录。
周二晚上开发商依然做了一些SQL优化,希望周三能够更顺畅一些。周三一早系统也确实比较平稳,让大家感到放心不少。没想到上午高峰刚刚过去,11点半左右的时候又风云突变了。服务器的SYS% CPU使用率又飙升到70%以上,这回的问题发生了变化,不是并发DDL的问题了,而变成了enq:SQ等待了。老DBA一看到这个锁等等就很快就明白了,肯定又是某个或者某些SEQUENCE的CACHE用了默认的20,在高并发场景下冲突太严重了。开发商也很奇怪,今天这个出问题的模块上线多年了,以前从来没出过事,今天怎么就出事了呢。实际上问题很简单,以前有更烂的应用在前面挡着,也轮不到这个模块出事,前面的障碍扫除了,它才会显现出来。
经历了上午的风波后,下午系统运行还算平稳。虽然经过三天,系统一天天在转好。但是我还是不敢掉以轻心,对于如此庞大的黑匣子,后面还有哪些坑在等着我们,还真的不好说。