昨天一个老同学找我说碰到了数据库的问题,因为各种杂事一直给耽误了下,今天做了一个初步的分析。 

首先这是一个做统计业务的数据库,类型可以归为OLAP方向。根据反馈,在周末的时候相关的ETL任务会卡住,问题已经过去了一段时间,确切的说是发生了10月份的时候了,经过一段时间的排查发现问题是有规律的。所以想让我看看数据库层面有哪些潜在的问题,可以把这个问题解决掉。

首先我要到了一份AWR报告。整体看配置还是很不错的,小机下的11g RAC环境,硬件配置也是蛮不错的。

Oracle性能排查小案例_经验分享

这里的DB time还是很高的,这也就能够间接说明是在ETL出现问题很可能和这个DB time异常是有关的。

看到这里我需要去明确既然是RAC环境,另外一个节点是否也有类似的问题,结果很快排除了,只在这个节点2上存在性能抖动,节点1上的负载可以忽略不计。

这是节点2一个概览信息。

Oracle性能排查小案例_经验分享_02

里面有几个指标是很明显的,比如redo日志量实在是太高了,整体来看IO方面,压力还是蛮大的。

  这个等待事件也是比较典型的,可以更加明确问题的方向了。

Oracle性能排查小案例_经验分享_03

按照目前的信息,可以基本得到一个数据,每秒产生28M的redo日志量,那么1分钟会产生28*60近1.4G的日志,如果是一个小时,产生的redo就有80G左右。

可以看到等待事件,很多也是和redo方向相关的,排在首要的是日志切换频率的问题。 

这是时间模型的一个概览。 

Oracle性能排查小案例_经验分享_04

基于以上的信息,我们可以更加关注于IO层面相关的SQL,结果一看一个准。

Oracle性能排查小案例_经验分享_05

通过这个可以很明显的看到问题的瓶颈了,原来是有几个delete语句,经过确认这些delete语句是没有where条件的,也就意味着这是一个权标数据的清理,显然使用truncate是正确的解法。

经过了解,这属于ETL的一个流程,会先清理掉之前的数据,然后通过绑定变量批量写入数据的方式,调用的频率都是百万级别。

报告里面有一小栏不太起眼,通过这个指标能够明确的定位到问题。 

Oracle性能排查小案例_经验分享_06

在1个小时的时间里,日志切换了500多次,按照日志写入的情况,一个小时80G左右的日志,切换500次,那么redo文件的大小在150-200M之间,对于目前的这个配置和当前的问题来说,是很不合理的,按照问题发生时的情况,每隔7秒钟左右就完成一次日志切换。这个频率和我们预期的相差太大。

其实问题到了这里基本能够定位明确了。

不过老同学反馈了几个疑惑的问题,这个任务在每天都会执行,但是不是每天出问题,出问题的时间段经过观察发现比较规律,基本都是周末的时候出现问题。所以我需要继续明确下这个问题的潜在原因。 

经过排查,这个数据库里面没有发现业务层面的scheduler任务,而且对比相邻天数同样时间的awr报告,没有发现等待的delete语句。 

这有几种情况,一种是确实执行了delete,因为数据量不大,所以delete的结果完全可控,另外一类是这个任务的执行是有窗口时间的,是不是可能在周日的时候启动了业务层面的任务导致了这个问题。 这一点需要在ETL的相关配置中确认。

当然一种潜在的影响是数据库中默认会在晚上10:00开始一些定时任务,比如统计信息收集,日志清理等。这个影响是潜在的,如果存在不规范的delete方式,对于后端自动任务的执行性能是有潜在的隐患的。 

所以最后的一个结论是:

  1. 把delete操作改造为truncate操作,这应该是这个问题出现的关键解决拌饭

  2. 调整redo的大小,如果按照1G的redo来计算,则将近1分钟切换一次,相比原来的方式要好很多了,况且有了第1个方案的保证,这个的压力会减少40%左右

  3. 查看周日的定时任务,需要统一检查,然后禁用掉这列后端任务。 

    相信这样一波改进之后,这个问题能够得到根本性的解决。