400-920-0692
技术资源

高能预警

美美的五一假期第一天,7点不到就被客户电话吵醒,那叫一个扎心,但是本着客户就是上帝的服务精神,马上掏出电脑开始远程检查客户。客户有一套Linux6.5+Oracle11.2.0.4.160719生产环境的RAC对应的业务不可用,服务器CPU资源使用率飙升,业务发生严重卡顿,几乎不可用,同时alert后台发现如下报错:

Sat Apr 29 06:45:33 2017

Errors in file xxx_ora_44138.trc  (incident=299353):

ORA-00600: 内部错误代码, 参数: [ktecgsc:kcbz_objdchk], [0], [0], [1],[], [], [], [], [], [], [], []

Incident details in: xxx_ora_44138_i299353.trc

Use ADRCI or Support Workbenchto package the incident.

See Note 411.1 at My OracleSupport for error and packaging details.

除了上面这个报错外,还可能会伴随以下报错:

ORA-00600: 内部错误代码, 参数: [ktspgsb-1], [], [], [], [], [], [],[], [], [], [], []

ORA-00600: 内部错误代码, 参数: [ktecgsc:objdchk_kcbgcur_3], [302047],[4], [0], [0], [], [], [], [], [], [], []

紧急救场

首先我们第一时间搜索MOS文章,发现有几篇文章比较接近,分别是以下文章:

《ORA-600[ktecgsckcbz_objdchk] while TRUNCATE a table (Doc ID 2230425.1).docx》

《ORA-00600[ktecgsckcbz_objdchk] on 11.2 (Doc ID 1562473.1).docx》

这几篇文章基本上都提到了可能和truncate语句和查询语句触发bug有关。我们的trace中发现的语句为:

----- Current SQL Statement forthis session (sql_id=1kznzqr29hdt5) -----

INSERT INTO SOME_TABLE (XIDUSN,XIDSLT, XIDSQN, OWNER, TABLENAME, RECORDID, OWNERSUB, TABLENAMESUB, COLUMNNAMESUB,RECORDIDSUB, COLLECTDATE, PARTFLAG) SELECT :B4 , :B3 , :B2 , R.OWNER,R.TABLENAME, R.RECORDID, R.OWNERSUB, R.TABLENAMESUB, R.COLUMNNAMESUB,R.RECORDIDSUB, SYSDATE, CEIL((0.1 + TO_CHAR(SYSDATE, 'MI')) / 15) FROMTABLE(:B1 ) R

我们自己第一时间对这个表进行了校验,一切正常:

SQL> @?/rdbms/admin/utlvalid.sql
Table created.
SQL> ANALYZE TABLE LOG.SOME_TABLE VALIDATE STRUCTURE CASCADE;
Table analyzed.
SQL>

为了快速恢复业务,我们和客户商量重启实例看看问题能不能恢复。由于报错发生在节点一,为了能方便我们收集一些状态数据,我们首先重启了节点二。这个时候发现,节点二重启完成后,系统居然都恢复正常,节点一也不再报错,业务人员也反映系统已恢复。接下来就是确认问题原因和解决方案,由于是客户核心系统,我们第一时间开了1级的SR,很快官方工程师参照《ORA-600[ktecgsckcbz_objdchk] while TRUNCATE a table (Doc ID 2230425.1).docx》这篇文章,让我们对相关对象进行校验。通过我们现场工程师的操作,所有的校验都通过,结果反馈给原厂工程师后,原厂工程师回复可能触发了bug19689979。我们找到了这个bug相关的两篇说明文章《Bug19689979 : ORA-8103 RUNNING SELECT ON PARTITION TABLE ON RAC NODE》Bug19689979 - ORA-8103 or ORA-600 [ktecgsckcbz_objdchk] or Wrong Results onPARTITION table after TRUNCATE in 11.2.0.4 or above (文档 ID19689979.8)。很明显,这两篇文章都提到了对分区表进行truncate操作有可能触发bug。这个bug的基本信息如下:

  1. 系统一般为RAC环境;

  2. 该bug从11.2.0.4引入,直到12.2的安装程序才包含了该bug对应的补丁;

  3. 该bug一般是由于对分区表进行truncate或drop触发;

  4. 该bug触发时后台会报ORA-600[ktecgsc:kcbz_objdchk]错误;

  5. 通过flushshared_pool可以临时解决报错。

对比我们的case,我们的数据库版本是11.2.0.4.160719,应用人员确认,我们确实存在一个job,每隔一分钟会truncate一个表的分区,我们的alert后台最开始的报错确实是ORA-600 [ktecgsc:kcbz_objdchk],尽管我们的问题临时解决是通过重启节点二的实例来实现的,其实重启后shared_pool必然会重新分配,可以等价于刷新了shared_pool。至此,基本上可以认为我们成功的命中了Bug 19689979。关于该bug,官方的解释是11.2.0.4之后的版本为了解决之前版本中对一个DDL语句计数器进行截断,导致结果集可能出错的问题时引入了该bug。触发bug的原因是计数器只有5位,可能溢出就会触发该bug。详细的解释请见《Bug19689979 : ORA-8103 RUNNING SELECT ON PARTITION TABLE ON RAC NODE》。针对该bug解决方案有以下三种:

  1. 打补丁相应的19689979补丁;

  2. 修改隐含参数"_part_access_version_by_number"为FALSE;

  3. 临时性解决方案是执行alter system flush shared_pool.

bug重现

但是由于系统实在太核心了,因此,最好能够重现这个问题,从而确认确实是由于这个bug导致的报错。于是,我们搭建了一套测试环境进行问题重现。我们通过几个脚本进行自动化测试,差不多4个小时不到,问题得到了重现,换句话说,只要是满足以下几个条件的系统,极其可能触发该bug:

  1. 版本为11.2.0.4到12.2之间,没有打过Bug19689979;

  2. 系统为RAC环境;

  3. 存在高频的truncate操作。

如果你的环境满足以上几个条件,请尽快打补丁修复,因为这个问题得到了重现,就意味着条件满足的情况下,出现问题的概率极大。一旦出现这个问题,那么就会导致后台不断报错,日志和trace大量生成,与此同时相关对象上的语句在没有flushshared_pool之前会一直报错,导致性能下降明显,相关业务不可用。

这里为了方便大家验证,我们分享出我们重现问题的脚本,相关说明如下:

名称作用备注
prepare_data.sql准备数据
query_insert_action.sh执行数据查询、插入和删除目的是保证测试表中有数据,查询能有结果;随机删除数据是为了确保空间占用不无限制增大
truncate_action.sh执行truncate分区动作
check_ora-600.sh出现报错自动刷新shared_pool由于采用了自动测试,为了防止频繁报错可能导致测试环境系统不可用,进行的系统保护措施

两个脚本的调度命令如下:

 nohup /home/oracle/query_insert_action.sh &

 nohup /home/oracle/truncate_action.sh &

为了不至于把测试服务器资源耗尽,每隔5分钟会执行check_ora-600.sh,确保触发bug后能够自动刷新shared_pool,调度任务如下:

*/5 * * * * sh /home/oracle/check_ora-600.sh

脚本下载链接: https://pan.baidu.com/s/1mifXNio 密码: r9xs