问题背景:
在一套数据库的版本为11.2.0.4.160719的Oracle RAC集群,应用程序执行语句出现异常失败,应用日志显示出现ORA-00600: internal error code, arguments: [ktecgetsh-inc], [1], [], [], [], [], [], [], [], [], [], []报错
问题分析:
从数据库的alert日志,可以发现出现大量的ORA-00600: internal error code, arguments: [ktecgetsh-inc], [1]报错
Wed Jan 10 09:51:52 2024
DDE: Problem Key 'ORA 600 [ktecgetsh-inc]' was completely flood controlled (0x6)
Further messages for this problem key will be suppressed for up to 10 minutes
Wed Jan 10 10:02:49 2024
Errors in file /oracle/app/oracle/diag/rdbms/db/db1/trace/db1_ora_65616.trc (incident=417115):
ORA-00600: internal error code, arguments: [ktecgetsh-inc], [1], [], [], [], [], [], [], [], [], [], []
Incident details in: /oracle/app/oracle/diag/rdbms/db/db1/incident/incdir_417115/db1_ora_65616_i417115.trc
Wed Jan 10 10:03:19 2024
Thread 1 advanced to log sequence 172591 (LGWR switch)
Current log# 5 seq# 172591 mem# 0: +DATA/db/onlinelog/group_5.272.926677033
查看报错的的incident文件日志内容,可以发现触发的都是同一条insert语句
Current SQL Statement for this session (sql_id=ca8crs4qr2wp6)
insert into XXX.XXX_SERVICE_LOG (access_token, exception, file_name, info, ip, time, type, id) values (:1 , :2 , :3 , :4 , :5 , :6 , :7 , :8 )
查看触发报错调用的函数堆栈信息,主要是调用insert数据的函数
kgdsdst()<--skdstdst()<--ksedst1()<--ksedst()<--dbkedDefDump()<--ksedmp()<--ksfdmp()<--dbgexPhaseII()<--dbgexProcessError()<--dbgeExecuteForError()<--dbgePostErrorKGE()<--dbkePostKGE_kgsf()<--kgeadse()<--kgerinv_internal()<--kgerinv()<--kgeasnmierr()<--ktecgetsh()<--ktecgshx()<--ktspisc()<--ktspgsp_main()<--kdtgsp()<--kdtgsph()<--kdtgrs()<--kdtInsRow()<--qerltcNoKdtBuffered<--InsRowCBK()<--qerltcSingleRowLoad()<--qerltcFetch()<--insexe()<--opiexe()<--kpoal8()<--opiodr()<--ttcpip()<--opitsk()<--opiino()<--opiodr()<--opidrv()<--sou2o()<--opimai_real()<--ssthrdmain()<--main()
根据ORA-600报错调用的函数对象ktecgetsh-inc,调用的堆栈以及数据库的版本号到Oracle官方mos查找该错误的匹配文档
发现有mos文档2297992.1与22855193.8描述的Bug 22855193匹配度很高
ORA-600[ktecgetsh-inc] and ORA-600 [opiexe0] Errors in a RAC Environment after ALTER TABLE SHRINK SPACE or ALTER INDEX SHRINK SPACE (Doc ID 2297992.1)
Bug 22855193 - ORA-600 [ktecgetsh-inc] Error During DML after Shrinking Table or Index (Doc ID 22855193.8)
在Oracle11.2.0.4、12.1.0.2版本RAC集群环境下,Bug 22855193对于分区表或者分区索引进行shrink space空间碎片整理之后,由于共享内存里面的元数据出现损坏,导致insert语句可能出现失败报错ORA-600 [ktecgetsh-inc][1]
确认当前问题是否匹配Bug 22855193的描述场景以及触发条件
1 当前问题环境为11.2.0.4.160719的Oracle RAC集群匹配bug描述信息里面的影响版本11.2.0.4以及RAC环境,修复补丁是单独的oneoff补丁,没有包含在PSU里面
2 报错incident的函数堆栈匹配mos里面描述的错误堆栈信息
ktecgetsh <- ktecgshx <- ktspisc <- ktspgsp_main2 <- kdtgsp <- kdtgsph <- kdtgrs<- kdtInsRow <- qerltcNoKdtBufferedInsRowCBK <- qerltcSingleRowLoad <- qerltcFetch
3 报错的对象和操作类型匹配,对分区表进行insert操作
4 插入的分区表有执行过shrink space的操作
确认分区表是否有执行过shrink space操作,查看插入的表的操作历史,在当天有执行过alter table的操作
查询具体的执行语句文本,发现只显示了alter table xxx.xxx,没有具体的操作执行内容,没法百分百确认分区表有执行过shrink space,而数据库的归档日志也早已经被删除,无法通过logmnr分析日志里面的具体内容,具体操作内存只能等后续询问其他的相关运维人员进行确认
综合上面的匹配条件,当前问题与Bug 22855193的匹配度还是很高的,除了执行shrink space操作存在不确定之外,其他条件都是匹配的,基本可以确认是Bug 22855193导致的insert执行语句报错ORA-00600: [ktecgetsh-inc], [1]问题,接下来的问题修复我们就按照mos文档给出的方向进行
问题修复:
官方的mog给出的修复方法有3点:
1 安装补丁Patch 22855193进行修复,这个当前环境是在线的生产环境,直接安装补丁基本没有操作的可行性
2 如果数据库的隐含参数_ptn_cache_threshold>0(控制分区元数据缓存的标志)则可以通过刷新shared pool进行解决
检查当前数据库的_ptn_cache_threshold值为0,条件不符合,刷新shared pool暂时先搁置
set pagesize 60 lines 1000 trimspool ON
col name format a40
col TYPE format a15
col description format a60
col value format a10
SELECT a.ksppinm name, b.ksppstvl value, b.ksppstdf defalt, DECODE (a.ksppity, 1, 'boolean',2, 'string', 3, 'number', 4, 'file', a.ksppity) TYPE, a.ksppdesc description
FROM sys.x$ksppi a, sys.x$ksppcv b
WHERE a.indx = b.indx
AND a.ksppinm LIKE '%ptn%cache%threshold%'
ORDER BY name;
3 在shrink space空间碎片整理完成之后,尝试多重跑几次insert语句,错误可能会自动消失,可以确认数据库当前没有正在执行的空间碎片整理操作,应用也重跑了几次,但ORA-600的错误依然在,没有自动消失,所以这种方式也不太可行
重新回到刷新shared pool的方法,虽然检查的_ptn_cache_threshold参数为0不符合文档上面说的刷新shared pool前置条件,但安装以往处理分区表异常的经历,遇到过的分区索引查询数据不一致,插入索引报ORA-00600[qesmaGetTblSeg1]错误,都是类似的内存里面的元数据出现损坏或者由于与磁盘块里面的元数据存在不一致导致的问题,临时的修复方法都可以通过尝试刷新shared pool进行规避,并且当前数据库的整体并发不大,刷新shared pool影响较小,所以最后还是决定通过刷新shared pool的方法进行尝试
在集群两个节点分别执行了刷新shared pool的操作,再让应用重新执行语句,语句这一次执行正常没有再报ORA-00600的错误了,问题得以解决
alter system flush shared_pool;