library cache lock等待事件是Oracle数据库较为常见的等待事件之一,产生library cache lock等待出现的原因有很多,如登录密码错误尝试过多、热表收集统计信息和SQL解析失败等。在Oracle 12c版本中,引入了一个新特性:分区表全局索引异步维护,这个新特性是指:当分区表有分区新增、删除、合并或truncate分区操作时,为了保证全局索引的有效性,通过调度JOB ( SYS.PMO_DEFERRED_GIDX_MAINT_JOB ) 默认在凌晨两点对全局索引进行维护。但是在特殊情况下会出现由于大量并发业务,造成异常library cache lock等待事件,造成数据库突发性能问题。在此,分享一次数据库性能故障的案例,供各位参考。
问题描述
某生产库收到异常告警信息,提示数据库出现大量等待告警。
当即登陆数据库,发现数据库出现大量library cache lock和library cache: mutex X等待。
问题分析
查看和异常等待事件相关的SQL,发现:
查看该SQL文本为:
insert into xxx.xx_LOG_INFO(xxx_ID,·······) values(:1 , :2 , :3 , :4 , :5 , :6 ) ;
而该SQL的执行计划并没有什么异常:
进一步分析ash,查看和异常等待事件相关的对象,发现:两个等待事件指向的object_id是相同的。
通过 object_id 查看对应的具体对象后,发现所有对象均和表 xxx. xx_LOG 相关。
此时,查看系统发现有一个进程正在进行 alter index 操作。
经查看:该索引 PK_xx_LOG 为表 xxx.xx_LOG 的主键索引。
而这个进程发现是系统的一个job,在当天的凌晨2点触发执行:
这个job 是Oracle 12C 的新特性----分区表全局索引异步维护:
当分区表有分区新增、删除、合并或truncate分区操作时,为了保证全局索引的有效性,通过调度JOB ( SYS.PMO_DEFERRED_GIDX_MAINT_JOB ) 默认在凌晨两点对全局索引进行维护。当dba_indexes表中的ORPHANED_ENTRIES字段为YES时表示这个全局索引需要被维护。通过查看,表 xxx.xx_LOG 的主键索引PK_xxx_LOG 确实需要被维护。
查看表 xxx.xxLOG 的DDL语句证实该表为 每天自动增加一个分区 的分区表。一般情况下,如果增加的新分区内不包含表内现有数据,是不会导致全局分区索引失效,但在当天凌晨1点,系统自动增加一个分区(split),新分区已经包括旧分区的部分数据,导致全局分区索引失效,从而触发了系统对全局索引的自动维护。而且该表比较大,维护分区索引的时间较长,从2点开始,到7点尚未结束,最终和大量insert的任务重叠,导致了最终问题。
通过向业务人员了解:表xxx.xx_LOG和xxx.xx_LOG_INFO是同时进行写入的。此时,故障原因变得十分清晰:
由于系统对表xxx.xx_LOG 上的主键索引进行维护,导致该表上的dml操作堵塞。而这两张表是同时进行写入,故通过查询SQL时出现的是另一张表,通过object_id查询时才发现问题所在。
问题解决
临时处理:经业务核实后将insert会话kill后,故障解决。
后续措施:
- 将insert业务错峰运行,避免再次出现类似情况。
- 批量增加分区表的分区,避免触发系统维护索引job运行。
- 可能的话,避免使用全局分区索引