且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

备库中ORA-00600错误的简单修复

更新时间:2022-09-02 10:09:30

最近偶尔会接到一条短信,提示某个备库中出现了ORA-00600的错误。对于这个问题还真不能心存侥幸,自己带着疑问查看了一下,
这是一个一主两备的库,主库和其中的一个备库没有任何的ORA-00600的错误,只有这一个备库中偶尔会出现ORA-00600的错误。
这个问题如果放大还是很严重的,比如主库出现问题了,如果切换到这个备库,那么ORA-00600的错误就会直接转移过来,这个时候这儿备库就有点鸡肋的味道了。所以这个问题一种思路就是重新搭建备库,另外一种就是手工修复。我还是更希望通过手工修复的方式来先来看看能不能解决掉这个问题。
报错的备库数据库日志如下:
Media Recovery Waiting for thread 1 sequence 654 (in transit)
Recovery of Online Redo Log: Thread 1 Group 7 Seq 654 Reading mem 0
  Mem# 0: /U01/app/oracle/fast_recovery_area/TESTSOB0/onlinelog/o1_mf_7_9lo8zrpc_.log
Mon Sep 21 08:36:02 2015
Archived Log entry 650 added for thread 1 sequence 653 ID 0xfe9af939 dest 1:
Mon Sep 21 12:18:09 2015
Errors in file /U01/app/oracle/diag/rdbms/testb0/testob0/trace/ordermob0_ora_26830.trc  (incident=403849):
ORA-00600: 鍐呴儴閿欒?浠g爜, 鍙傛暟: [kdsgrp1], [], [], [], [], [], [], [], [], [], [], []
Incident details in: /U01/app/oracle/diag/rdbms/testob0/testob0/incident/incdir_403849/testob0_ora_26830_i403849.trc
Use ADRCI or Support Workbench to package the incident.
See Note 411.1 at My Oracle Support for error and packaging details.
Mon Sep 21 12:18:11 2015
Sweep [inc][403849]: completed
Sweep [inc2][403849]: completed
Mon Sep 21 12:18:11 2015
Dumping diagnostic data in directory=[cdmp_20150921121811], requested by (instance=1, osid=26830), summary=[incident=403849].
Mon Sep 21 12:37:06 2015
Errors in file /U01/app/oracle/diag/rdbms/testob0/testob0/trace/testob0_ora_26766.trc  (incident=403918):
ORA-00600: 鍐呴儴閿欒?浠g爜, 鍙傛暟: [kdsgrp1], [], [], [], [], [], [], [], [], [], [], []
Incident details in: /U01/app/oracle/diag/rdbms/testob0/ordermob0/incident/incdir_403918/testob0_ora_26766_i403918.trc
Use ADRCI or Support Workbench to package the incident.
See Note 411.1 at My Oracle Support for error and packaging details.
Mon Sep 21 12:37:08 2015
Sweep [inc][403918]: completed
Sweep [inc2][403918]: completed
Mon Sep 21 12:37:08 2015
Dumping diagnostic data 
而对于日志中提到的trace文件,得到的内容如下:
/U01/app/oracle/diag/rdbms/testob0/testob0/trace/testob0_ora_26766.trc 
*** 2015-09-21 12:37:04.930
*** SESSION ID:(1898.8357) 2015-09-21 12:37:04.930
*** CLIENT ID:() 2015-09-21 12:37:04.930
*** SERVICE NAME:(SYS$USERS) 2015-09-21 12:37:04.930
*** MODULE NAME:(JDBC Thin Client) 2015-09-21 12:37:04.930
*** ACTION NAME:() 2015-09-21 12:37:04.930
 
* kdsgrp1-1: *************************************************
            row 0x01c55b6f.1f continuation at
            0x01c55b6f.1f file# 7 block# 351087 slot 31 not found
KDSTABN_GET: 0 ..... ntab: 1
curSlot: 31 ..... nrows: 32
kdsgrp - dump CR block dba=0x01c55b6f
Block header dump:  0x01c55b6f
 Object id on Block? Y
 seg/obj: 0x12739  csc: 0x00.10bfb352  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x1c55481 ver: 0x01 opc: 0
     inc: 0  exflg: 0
而第一次抛出ORA-00600的错误,可以追溯到2014年了,所以还是一个遗留问题。
这个错误代表的含义是对应的索引ROWID,在数据表中找不到记录,还是有数据不一致的情况。
从trace文件里也可以看到,其实是在运行一条sql语句的时候抛出来的错误。
SELECT  nvl(count(distinct USER_ID),0) as userCount,nvl(SUM(goods_price),0) as total FROM TEST_ORDER WHERE (IS_SANDBOX   = 0 or IS_SANDBOX is null) and  (order_status = 2 or order_status = 4) and UPDATE_DATE >=to_date(:1,'yyyy-mm-dd') and UPDATE_DATE <to_date(:2,'yyyy-mm-dd')+1  and (substr(MEDIA_CHANNEL_ID,0,2)='10' or substr(MEDIA_CHANNEL_ID,0,2)='20')  AND app_id = :3
至于问题怎么定位,trace中的内容值得好好琢磨一下。
* kdsgrp1-1: *************************************************
            row 0x01c55b6f.1f continuation at
            0x01c55b6f.1f file# 7 block# 351087 slot 31 not found
这个就代表错误出现在7号数据文件,351087号数据块上。
可以通过下面的语句来定位错误是否在TEST_ORDER这个表上
SQL> select owner,segment_name,segment_type from dba_extents where file_id=7 and block_id<=351087 and (block_id+blocks)>=351087;
OWNER                SEGMENT_NAME         SEGMENT_TYPE
-------------------- -------------------- ------------------------------------------------------
TESTOB             TEST_ORDER             TABLE
对于这个问题,MOS中已经提供了完整的解决方法。
ORA-600 [kdsgrp1] During Table/Index Full Scans (文档 ID 468883.1)
一种是通过dump出来数据,然后设置对应的事件,重建修复
#1 alter system dump datafile 7 block 351087;            
另外一种是直接声明跳过那些坏块,可以直接使用dbms_repair来修复。
  execute dbms_repair.skip_corrupt_blocks('TESTOB','TEST_ORDER'); 
但是因为问题发生在备库所以还是无法运行这个包的。
SQL>    execute dbms_repair.skip_corrupt_blocks('TESTOB','TEST_ORDER'); 
BEGIN dbms_repair.skip_corrupt_blocks('TESTOB','TEST_ORDER'); END;
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-16000: database open for read-only access
ORA-00604: error occurred at recursive SQL level 1
ORA-16000: database open for read-only access
ORA-06512: at "SYS.DBMS_REPAIR", line 419
ORA-06512: at line 1
所以还是需要在主库来运行,尽管主库中还是没有这个错误的。
SQL>    execute dbms_repair.skip_corrupt_blocks('TESTOB','TEST_ORDER'); 
PL/SQL procedure successfully completed.
执行过程很快,修复后自己也在观察是否还收到过ORA的错误警告,按照目前的情况来看,这个问题应该还是顺利解决了,因为已经过去了快两周,之前每一两天就会抛个错误。