Oracle Dictionary Corruption and Ways to Analyze the Issue

Oracle Dictionary corruption can lead to various errors and database/instance crash. Some of the dictionary corruption may not be fatal and it may throw error only when a DML or DDL is attempted on the corrupted object. Here I am going through an ORA-600 error is raised when drop is attempted on a table.

ORA-00600: internal error code, arguments: [ktecgeb:kcbz_objdchk], [0], [0], [1], [], [], [], [], [], [], [], []

Trace file can show block information:

========= Dump for incident 2610246 (ORA 600 [ktecgeb:kcbz_objdchk]) ========
—– Beginning of Customized Incident Dump(s) —–
Input data (nil), 0, 0
Formatted dump of block:
buffer tsn: 238 rdba: 0x3500034 (1024/55574580)
scn: 0x0973.5f32285d seq: 0x02 flg: 0x04 tail: 0x285d0602
frmt: 0x02 chkval: 0x3b14 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1

Most probably

SMON trace should be generated with more information it might say

*** SESSION ID:(1441.1) 2016-03-12 05:31:00.643
OBJD MISMATCH typ=6, seg.obj=-2, diskobj=320345892, dsflg=0, dsobj=233801234, tid=233801234, cls=7
Incident 3005368 created, dump file: /dumps-01/diag/rdbms/dw8/dw8-1/incident/incdir_4565368/dw8-1_smon_29288_i4565368.trc
ORA-00600: internal error code, arguments: [ktecgeb:kcbz_objdchk], [0], [0], [1], [], [], [], [], [], [], [], []

Non-fatal internal error happened while SMON was doing temporary segment drop.
SMON encountered 1 out of maximum 100 non-fatal internal errors.

It means that SMON looked at the block and found obj id as 233801234 instead of 320345892. This is the OBJD MISMATCH SMON is reporting and it cannot continue the DDL operation it was supposed to perform

Basically the function call is “ktecgeb” that is trying pin the block in current mode so it can be updated. The error is raised because the sanity check failed.

select owner, object_name, object_type, to_char(created, ‘MM/DD/YY HH24:MI:SS’) created_date,
to_char(last_ddl_time,’MM/DD/YY HH24:MI:SS’) last_ddl,
status
from dba_objects
where OBJECT_ID in (233801234)

Most probably above statement will return no rows. Because object with id 233801234 may not even exist in the database now.

select segment_type, owner, segment_name, partition_name
from dba_extents
where file_id = 8 and 55574580 between block_id and block_id + blocks-1;

But above SQL will return a row. In my case it retuned following information.

SEGMENT_TYPE OWNER SEGMENT_NAME PARTITION_NAME
——————— ——— ——————- ———————–
TABLE PARTITION MY_TEST MY_TEST_TABLE MY_TEST_TABLE_PART1

SCN 0x0973.5f42282d of the block to actual SCN number turns out to be 10391124060205. To see how old is this SCN, verify the current SCN of the database.

SQL> set numwidth 20
SQL> select current_scn from v$database;

CURRENT_SCN
——————–
10418245156952

This is way ahead and it means that issue is very old. Let us see if the archive of the block change vector exists

SQL> alter session set nls_date_format=’dd-mm-yyyy hh24:mi:ss’;

Session altered.

SQL> select name, thread#, sequence#, first_time, next_time from v$archived_log where 10391124060205 between first_change# and next_change#;

no rows selected

If this archive file is available, we can dump the change vector and see what was the pervious state of the block.

Best option to fix this kind of issues is to enable row movement and do partition move.

alter table MY_TEST.MY_TEST_TABLE move partition MY_TEST_TABLE_PART1;

It is required to rebuild partition indexes as they become unusable after the move.