Oracle 10.2.0.3 Bind Peeked Parallel Bug

on

昨晚11:30,客户电话,报告数据库服务器CPU负载陡然上升到95%以上,并且报ORA-4031错误。12:00赶到现场。

查看故障发生期间的AWR报告。

1. 最高的等待事件是“latch: library cache lock”和“latch: library cache”
2. Shared Pool Memory Usage 达到了98% (Shared Pool Size: 4,096M)
3. SQL ordered by Elapsed Time部分显示一条SQL占用了91.9%的总时间
4. SQL ordered by CPU Time 部分显示同样这条SQL占用了91.9%的CPU时间
5. SQL ordered by Sharable Memory部分,大批Executions=N/A的SQL,并且最高的一条SQL已经消耗了将近2G的Sharable Memory
6. SQL ordered by Version Count部分,刚才那句占用了将近2G缓存的SQL有高达77,237的Version Count

至此,大概可以猜测整个问题的发生原因了。因为过度的Version Count导致Shared Pool消耗殆尽,在Library Cache中开始频繁获取空闲空间以parse新进的SQL,于是产生大量的library cache latch,最终Shared Pool中再也无法找到足够解析一个SQL的空闲空间,于是报ORA-4031。整个系统全线崩溃。

那么现在问题就在于为什么会有如此巨大的Version Count?

查询v$sql_shared_cursor视图,对于每句SQL,如果由于某种原因不能被共享而被重新parse生成一个cursor的话,就会在这个视图中多一条记录,同时记录了不能被共享的原因。

通过AWR报告中的sql_id,发现产生巨大Version Count的原因是BIND_PEEKED_PQ_MISMATCH,简单解释一下,就是说对于并行操作在有Bind_Peek时,Oracle认为整体条件不符合cursor共享的原则,于是便重新解析了。

应用里面的SQL是比较规范的,使用了绑定变量,但是巧就巧在:
1. 在Table级别,客户设置了parallel属性,导致对于该表的select操作,即使是白天的OLTP阶段也仍然使用了大量的并行进程
2. 因为绑定变量,所以Oracle决定在生成执行计划之前要Bind_Peek一下

这两个条件的合作触发了Oracle10g的一个BUG 4367986,本来不应该实际上却产生了这么多Version Count。

解决这个BUG的Patch目前只有Linux,Solaris和HP-UX平台的,而客户现在的AIX平台只有等待Oracle开发团队的Backport,希望在明天可以收到release的Patch。

权宜之计是:
1. 去除Table级别的Parallel设定(其实早就应该去除,因为在OLTP系统中设置表的并行值并不值得推荐)
2. 或者,禁用Bind_Peek,初始化参数中设置”_optim_peek_user_binds”=FALSE

客户选择了前者,目前整个系统功能正常。

屡次熬夜并且屡次早上睡了几个小时又被叫起来的经历之后,一个感想:

AWR报告,ADDM报告,ASH报告,这些10g的新利器需要DBA彻底地去熟悉,仔细再仔细,任何问题你都会找到蛛丝马迹的,然后串在一起,就会豁然开朗,柳暗花明。

3 Comments Add yours

  1. 木匠 says:

    你难道在OSS (Oracle Support) 部门?

  2. kamus says:

    我也有些恍惚,觉得自己似乎是在OSS,实际上偶确实是在OCS啊。。。

  3. 蛋白粉 says:

    ADDM和AWR确实蛮方便的,上了10g的DBA应该都去用用

Leave a Reply

Your email address will not be published. Required fields are marked *