ORA-07445: 出现异常错误: 核心转储(oracle bug)

来源:互联网 发布:怎么看淘宝店铺的类目 编辑:程序博客网 时间:2024/06/03 14:21

近来在测试时碰到一莫名问题,研发声称在开发环境中正常,而我们在测试环境中则经常遭遇,几番折腾,发现是oracle的bug所致。不过即使是oracle出bug,人家在metalink上也井井有条的写着从哪个版本到那个版本存在这样的问题,在什么版本上可以fix掉这个bug,在什么条件下会触发这个bug,又通过什么样的解决方案可以把这个bug规避掉。

所以说,bug到处都会有,而怎样让已知bug不会成为用户无法使用产品或者生产力无法提高的借口是非常重要滴...

废话少说,还是记下问题排查的过程,以备后查。

数据库版本:

oracle10.2.0.4

问题现象:

日志中出现如下报错:

2011-06-2110:2050,010: INFO [http-8180-Processor11|http-8180-Processor11] ([PublishSequenceDetailHibernateDao].java:307) - 准备数据存储过程参数:publishType[1]publishSeq[813007]currentFolderIds[37]2011-06-2110:2052,103:ERROR [http-8180-Processor11|http-8180-Processor11] ([PublishSequenceDetailHibernateDao].java:317) - 存取过程操作失败无法从套接字读取更多的数据 2011-06-2110:2052,104: INFO [http-8180-Processor11|http-8180-Processor11] ([PublishSequenceDetailHibernateDao].java:330) - 准备数据存储过程返回参数:N 2011-06-2110:2052,109:ERROR [http-8180-Processor11|http-8180-Processor11] (JDBCTransaction.java:155) - JDBC commit failed
java.sql.SQLException: 无法从套接字读取更多的数据 at oracle.jdbc.driver.[DatabaseError].throwSqlException([DatabaseError].java:112) at oracle.jdbc.driver.[DatabaseError].throwSqlException([DatabaseError].java:146) at oracle.jdbc.driver.[DatabaseError].throwSqlException([DatabaseError].java:208) at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1118) at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1070) at oracle.jdbc.driver.T4C7Ocommoncall.receive(T4C7Ocommoncall.java:106) at oracle.jdbc.driver.T4
CConnection.doCommit(T4CConnection.java:523)

oracle alert日志中出现如下报错

Errors in file /oracle/oracle/product/10.2.0/db_1/admin/test/udump/test_ora_2451.trc:
ORA-07445: exception encountered: core dump [opiptp()+56] [SIGSEGV]
[Address not mapped to object] [0x7F8777FAF080]

不同数据库环境的现象:

测试环境中,数据库版本为oracle10.2.0.4,出现此问题的概率极大;
开发环境中,数据库版本为oracle10.2.0.1,则不会出现此问题。
现场环境中,数据库版本为oracle10.2.0.4,存储过程逻辑大致相同,也不会出现此问题。

经过研发同学的排查,最终定位到存储过程在执行下列sql的时候,测试环境的数据库alertlog中,就会不断的出现ORA-07445的错误。

insert into vod_cms_publish_seq_detail nologging
select PUBLISH_SEQUENCE.nextval, 812486, 1,x.id,null,x.assettype,decode(x.status, 3, 41, 40),x.folderid,x.assetid
FROM vod_cms_cont2flder x WHERE x.pubauditstatus=4 and x.locatestring LIKE substr('1#2$2', 1, instr('1#2$2', '$') - 1)||'%';

该sql在现场正式环境中的oracle10.2.0.4数据库中也可正常运行,唯一区别是,现场正式环境的vod_cms_cont2flder对象为数据表,而测试环境中因代码重构,该对象实际是视图。

尝试将insert之后的append hints去掉,该sql即可正常执行,将整个发布准备数据的存储过程中所有的append hints去掉后,发布功能恢复正常。是否问题就出在这个append的hints上么?

还需要在metalink上查证问题根源。

问题分析

浅析ORA-07445错误

一般情况下,ORA-600被证明为oracle的内部错误,通常由oracle的bug引起,需要打oracle相应的补丁程序。而当oracle服务器进程从操作系统收到一个致命的错误信息时会抛出ora-07445错误,这个错误可以被oracle后台进程或者用户进程激发。当错误被抛出时,系统会首先写一个错误日志到alert.log文件中,然后会写跟踪文件到user_dump_dest或background_dump_dest中;最后会将主存信息转储到core_dump_dest中。
操作系统有很多的非法操作设计,一个经常会碰到的情况就是,当一个进程访问一个非法地址(比如系统预留地址)时致命错误将会产生。
Ora-07445错误是一个非常普通的错误,可能在oracle的任何代码中产生,该错误代码更详细的描述需要进一步跟踪其跟踪文件。

问题根源分析

在metalink上输入关键字:ORA-07445: exception encountered: core dumpopiptp()+56SIGSEGV,可以搜到id号为1069487.1的一篇文章,文中说明,在10.2.0.4版本至11.1.0.6版本,存在一个bug,如果数据库的OPTIMIZER_MODE参数值为ALL_ROWS的时候,从视图中查询数据时会触发此bug,从而导致出现ORA-07445的报错。

在10.2.0.2以下的版本,则没有这个bug,所以解释了测试环境中有而开发环境中无的现象;现场版本使用的是对象表,不是视图,所以也没问题...

然而在该文档中并未提到insert 这个动作是否会触发bug,虽然从现象上看去掉append的hint之后,问题就不再出现,但是问题的根源是否就找到了呢?根据该文档中提供的解决方案,执行以下sql修改隐含参数之后,让测试恢复insert 的hint,继续观察测试的结果。

alter system set "_optimizer_rownum_pred_based_fkr"=false;

果然没过多久,同样的问题继续出现...只好继续回头分析alert日志中提到的trace文件,/oracle/oracle/product/10.2.0/db_1/admin/test/udump/test_ora_2451.trc,发现日志中有如下内容:

ksedmp: internal or fatal error
ORA-07445: exception encountered: core dump [opiptp()+56] [SIGSEGV] [Address not mapped to object] [0x7F981BBE34D8] [] []
Current SQL statement for this session:
select T.* FROM T_PAGE T START WITH T.ID = :B1 CONNECT BY PRIOR T.PARENT_ID =T.ID

额...仔细分析vod_cms_cont2flder视图的生成sql,发现这个视图不简单哪,竟然还调用了一个函数,函数中则使用了上述connect by prior递归查询的sql,好吧,继续metalink...

这次通过关键字 ORA-07445 core dump opiptp CONNECT BY PRIOR 的组合进行查询,可以搜到id号为436199.1的一篇文章,文中说明,在10.2.0.2版本至10.2.0.5版本,存在bug 5968363,假如尝试使用insert append,或者在查询中存在CONNECT BY, WITH, 函数调用等复杂操作时,会触发此bug。宾果,版本、动作、现象全中,这才是问题的始作俑者嘛

解决方案

接下来的解决方案就简单了,根据oracle metalink上提供的solution,在数据库级别执行以下sql,以设置隐含参数,即可避免出现此问题。

alter system set "_optimizer_connect_by_cost_based" = false scope=both ;

或者在session级别执行下列sql:

alter session set "_optimizer_connect_by_cost_based" = false scope=both ;

或者直接在语句级别加hint:

当然,从本case的实际情况看,在数据库级别执行隐含参数的设置是最为合适的,避免在程序中做过多的改动。