数据恢复:ORA-600 kccpb_sanity_check_2解决

最近在客户的数据库恢复中再次遇到了ORA-00600 kccpb_sanity_check_2错误,这个错误是因为控制文件不一致导致的。

出现这个错误时,数据库将无法Mount挂载,影响数据库服务。
这个错误,多数是因为存储故障,丢失了数据写。

Oracle对此错误的解释是:

[kccpb_sanity_check_2] indicates that the seq# of the last read block is higher than the seq# of the control file header block. This is indication of the lost write of the header block during commit of the previous cf transaction.

其解释是:kccpb_sanity_check_2 表示最后读取的控制文件块其 seq# 控制序列号大于控制文件头块的 seq# ,这是不应该出现的情况。这说明在最后执行提交的控制文件事务(CF Transaction)中,对于头块的写入丢失了

这个错误如果只是存在于控制文件上,可以通过重建控制文件来解决,毫无疑问,这是最为简单的处理方式。
如果有备份,也可以从备份中恢复完好的控制文件,但是重建通常是很快捷的方式。

以下是一些错误的记录:

Fri Jan 16 10:47:45 2009
alter database mount
Fri Jan 16 10:47:50 2009
Errors in file /u01/app/oracle/admin/SZFDB/udump/szfdb_ora_7805.trc:
ORA-00600: internal error code, arguments: [kccpb_sanity_check_2], [1449], [1448], [0x000000000], [], [], [], []
Fri Jan 16 10:47:51 2009
ORA-600 signalled during: alter database mount…
Fri Jan 16 10:58:50 2009
alter database mount
Fri Jan 16 10:58:54 2009
Errors in file /u01/app/oracle/admin/SZFDB/udump/szfdb_ora_9233.trc:
ORA-00600: internal error code, arguments: [kccpb_sanity_check_2], [1449], [1448], [0x000000000], [], [], [], []

案例二:

Mon Aug 27 19:15:26 2007
ORACLE V10.2.0.1.0 – Production vsnsta=0
vsnsql=14 vsnxtr=3
Windows Server 2003 Version V5.2 Service Pack 2
CPU                 : 2 – type 586, 2 Physical Cores
Process Affinity    : 0x00000000
Memory (Avail/Total): Ph:2673M/3035M, Ph+PgF:4701M/4926M, VA:1938M/2047M
Mon Aug 27 19:15:26 2007
Starting ORACLE instance (normal)
LICENSE_MAX_SESSION = 0
LICENSE_SESSIONS_WARNING = 0
Picked latch-free SCN scheme 2
Mon Aug 27 19:15:37 2007
Using LOG_ARCHIVE_DEST_10 parameter default value as USE_DB_RECOVERY_FILE_DEST
Autotune of undo retention is turned on.
IMODE=BR
ILAT =18
LICENSE_MAX_USERS = 0
SYS auditing is disabled
ksdpec: called for event 13740 prior to event group initialization
Starting up ORACLE RDBMS Version: 10.2.0.1.0.
System parameters with non-default values:
processes                = 150
__shared_pool_size       = 230686720
__large_pool_size        = 4194304
__java_pool_size         = 4194304
__streams_pool_size      = 0
sga_target               = 612368384
control_files            = E:\DB_SERVER_GROUP\ORACLE\PRODUCT\10.2.0\ORADATA\ADB\CONTROLFILE\O1_MF_3B37YF0H_.CTL, E:\DB_SERVER_GROUP\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\ADB\CONTROLFILE\O1_MF_3B37YF8S_.CTL
db_block_size            = 8192
__db_cache_size          = 364904448
compatible               = 10.2.0.1.0
db_file_multiblock_read_count= 16
db_create_file_dest      = E:\DB_Server_Group\Oracle\product\10.2.0\oradata
db_recovery_file_dest    = E:\DB_Server_Group\Oracle\product\10.2.0\flash_recovery_area
db_recovery_file_dest_size= 21474836480
undo_management          = AUTO
undo_tablespace          = UNDOTBS1
remote_login_passwordfile= EXCLUSIVE
db_domain                =
dispatchers              = (PROTOCOL=TCP) (SERVICE=adbXDB)
job_queue_processes      = 10
audit_file_dest          = E:\DB_SERVER_GROUP\ORACLE\PRODUCT\10.2.0\ADMIN\ADB\ADUMP
background_dump_dest     = E:\DB_SERVER_GROUP\ORACLE\PRODUCT\10.2.0\ADMIN\ADB\BDUMP
user_dump_dest           = E:\DB_SERVER_GROUP\ORACLE\PRODUCT\10.2.0\ADMIN\ADB\UDUMP
core_dump_dest           = E:\DB_SERVER_GROUP\ORACLE\PRODUCT\10.2.0\ADMIN\ADB\CDUMP
db_name                  = adb
open_cursors             = 300
pga_aggregate_target     = 203423744
PSP0 started with pid=3, OS id=2396
PMON started with pid=2, OS id=2392
MMAN started with pid=4, OS id=2400
DBW0 started with pid=5, OS id=2404
LGWR started with pid=6, OS id=2408
CKPT started with pid=7, OS id=2412
SMON started with pid=8, OS id=2416
RECO started with pid=9, OS id=2420
CJQ0 started with pid=10, OS id=2424
MMON started with pid=11, OS id=2432
Mon Aug 27 19:15:54 2007
starting up 1 dispatcher(s) for network address ‘(ADDRESS=(PARTIAL=YES)(PROTOCOL=TCP))’…
MMNL started with pid=12, OS id=2444
Mon Aug 27 19:15:54 2007
starting up 1 shared server(s) …
Mon Aug 27 19:16:00 2007
alter database mount exclusive
Mon Aug 27 19:16:07 2007
Errors in file e:\db_server_group\oracle\product\10.2.0\admin\adb\udump\adb_ora_2472.trc:
ORA-00600: internal error code, arguments: [kccpb_sanity_check_2], [1558], [1423], [0x0], [], [], [], []

Mon Aug 27 19:16:40 2007
ORA-600 signalled during: alter database mount exclusive…

适当的备份控制文件的创建语句,在恢复时可能会起到很大的帮助作用。

某省公安厅数套Oracle RAC(ASM)恢复案例

前不久帮助某客户恢复了6套Oracle RAC,均为ASM,而且版本均为10.2.0.4。熬夜好几天,差点吐血了。这里以其中一套库的恢复进行简单说明,跟大家分享。
其中几套基本上都遇到了如下的ORA-00600 错误:

对于该错误,其实很简单,主要是因为控制文件损坏,通过重建控制文件或者利用备份的控制文件进行restore即可进行mount;甚至于我们利用控制文件快照都可以进行数据库mount;然后接着进行恢复操作。在恢复的过程中还遇到了如下的错误:

上述的ORA-00600错误其实很简单,主要是数据块SCN的问题。这里以其中一套库的恢复进行大致说明,因为在恢复该库的过程中,遇到了一件十分神奇的事情。

由于是ORACLE RAC,因此重建控制文件之后,是需要添加redo logfile的;然而add logfile 发现报上述错误。根据Oracle metalink的一些方法均不能成功,都报上面的错误,确实很怪异。
有些人看上述的错误,可能会认为是设置了OMF的参数,其实这里并不是,我将相关参数全部修改之后,错误依旧。
这里实际上添加logfile时,只写磁盘组名称就行了,不需要写绝对路径。
接着在进行recover后进行open resetlogs打开时,报错ORA-01248,如下:

这个错误还是比较少见,实际上网上那些说法,以及Oracle mos提供的解决方法我发现都不行。
无奈只能先将其offline ,然后再进行恢复。再进行open之前我查询了当前的checkpoint scn如下:

由于open失败,这里我想着是不是这2个文件有问题,又用之前的快照控制文件进行recover一把,然后再次用重建的控制文件起来数据库进行recover,发现神奇的事情出现了:

我们可以看到open 失败了,对于open失败的 情况,我们首先是看alert log,接着10046 trace。

这里我又屏蔽了undo相关的参数。再次尝试发现错误依旧。再次启动,神奇的事情出现了,SCN居然倒退了?

很明显,这个133的scn 回退到了过去2年前了,出现时空穿越了。。。。 当然,open肯定还是报错:

这里先不管为啥连数据文件头的SCN都倒退了(之前被offline的2个文件scn是OK的).  通过10046 trace得到如下内容:

我们这里可以看到,这里报错的SQL读取了file 1 block 218,以及file 40 block 167538。
对于file 1 block 218,我dump 发现没有活动事务;而file 40 block 167538则为undo 块.

同时dump 了这个undo 块,发现确实感觉有些异常,如下所示:

由于所有的文件头SCN 都倒退了,正常open 都报错,只能推进SCN,而且SCN必须要比这个undo block的最大SCN 还要大一些才行,通过在pfile文件中加入参数*._minimum_giga_scn即可。

顺利打开数据库之后,立即将原有的undo 表空间进行drop 并重建。
虽然数据库是打开了,然而其中有2个数据文件之前被我们offline了,而且中间进行了resetlogs操作,因此现在无法进行正常online了。

这里用bbed 将上面2个文件头相关信息修改掉,然后进行recover,可以顺利online文件。

最后建议将数据库expdp 导出并重建。到此告一段落!

某客户Oracle RAC(4 TB ASM) 数据库恢复案例

6月底我们接到某客户的紧急支持请求,其客户数据库在不久前由于机房停电,导致数据库重启后无法启动。

我们通过teamviewer远程初步分析了alert log以及kfed读取了几个disk 发现,数据库无法启动的根本原因在于ASM diskgroup无法mount。而ASM diskgroup 无法mount的根本原因在于,ASM元数据出现损坏,其中表现为ASM 启动时无法进行事务恢复。

这里我们先不去纠结为什么会坏。对于asm的元数据如果出现损坏,那么修复的难度可想而知。

这里我采取了非常简单的数据库恢复方案,计划用AMDU抽取数据库文件,然后将数据库open,最后再重建原数据库磁盘组,最后通过Oracle rman 的backup as copy 方式将数据库还原回去。

想象是比较美好的,经过与客户长达1天的沟通协调之后,发现客户根本协调不到存储资源,而数据库环境本地可以空间也就不足100G。我们知道,整个数据库的磁盘组是6TB,其中数据库文件大约在4T左右,显然这是比较麻烦的事情。

无奈之下,客户从京东买了一个6TB的移动硬盘,经过一番努力之后,挂上移动硬盘,通过AMDU抽取文件测试,发现速度大约为5m/s。这是一个500m的undo文件复制到移动硬盘的速度测试:

大家可以计算一下,大约需要10天左右。这样是这样进行下去,那么整个恢复过程估计需要15天了,这是无法接受的。

后面跟客户了解了一下,客户的应用服务器是windows环境,我通过在windows共享文件,NFS共享到soalris,测试amdu抽取文件的速度大约可以达到15m/s。虽然这也是非常之慢的,但是相比之前已经好很多了,客户也可以接受了。

这里不得不说一下windows和Soalris之间配置NFS共享,也是一个比较麻烦的事情。折腾了几个小时才搞定这个问题。这里我简单记录一下配置的步骤,如下:

后续的步骤相对就简单了,都是传统的数据库恢复套路。如下是AMDU抽取文件的步骤:

这里我们需要注意的是,amdu不仅可以抽取数据文件,还可以抽取spfile、controlfile、以及redo、archivelog等。

对于AMDU工具抽取文件的过程,就单纯的命令而言,这是比较简单的。其中的关键就是我们必须知道文件在ASM diskgroup中对应的asm file number号。注意,这里的file number,并非数据库(DB)中的file number。

Oracle ASM的元数据中,其中alias directory 里面记录了数据库文件和asm 之间的一个映射关系。也就是说我们只要能够通过kfed读取alias 的数据,也就能够知道数据文件的asm file number是多少。

当然,很多情况之下,如果你添加数据库文件是alter tablespace xxx add datafile ‘+DATA’  …这样的方式,那么直接查询控制文件即可获得asm file number。这里不多说。

最后我dbv check了一下数据库文件,发现就undo存在几个坏块,其他文件均ok。不过比较郁闷的是,进行正常recover database恢复时,提示需要recover的归档找不到。这是怎么一回事呢?

我们来看下数据库文件头的scn 情况。

我们可以发现,从文件头的scn来看,差距大概在3个小时左右。而recover 时也确实需要比较旧的archivelog。而这中间差距的几个小时的归档,我们通过kfed 读取asm diskgroup元数据发现并没有找到。

为什么会丢失呢?其实很简单,可能这3个小时的归档也就6个archivelog,很可能在存储cache中,并没有写入到磁盘上。那么当掉电之后,这几个archivelog 肯定也丢失了。

当归档不全的情况之下,我们amdu抽取的current redo logfile已经没有意义了。我们只能将该数据库强制open,然后重建数据库。这里我简单描述一下数据库的open过程,以及恢复过程中遇到的一些错误:

首先利用amdu 抽取的控制文件进行mount,发现报如下错误:

这个错误很常见,我们在数据库恢复过程中经常碰到该错误。假设你是第一次遇到这个错误,你该如何判断该错误是什么问题?跟什么东西有关系呢?从ORA-00600错误的关键字,kccpb可以看出,这跟控制文件有关系,其中还包含了check关键字。说明这是在数据库mount过程中,进行某些check检查,发现了某些数据异常。那么后面的2个数字:3811063,3770626是什么意思呢?

有人或许会说,这有没有可能是scn?这里不排除这种可能性,如果你稍微有一定经验,那么很容易排除这个可能性。为什么?

首先对于一个运行超过3年的Oracle数据库,scn不可能这么小。其次从Oracle 10g开始,会自动产生snap controlfile的备份,在ORACLE_HOME/dbs目录下,我们可以利用该备份进行mount,然后去检查数据库文件的scn情况。

那么这个错误到底是什么意思呢?这里我猜测肯定是某个sequence number的东西,Oracle在mount的过程中认为读取的数据应该是3811063,但是实际上读取的数据确实3770626,2者之间存在差异。也就是说,Oracle认为控制文件已经损坏。

实际上,Oracle metalink 针对该错误进行了详细描述,其实也提供了解决方案,供大家参考:ORA-00600: [kccpb_sanity_check_2] During Instance Startup (文档 ID 435436.1)

看过该文档的人应该都知道,解决该错误的方法就是利用备份进行恢复,要么就是重建控制文件。既然如此,那么我们就来重建控制文件吧:

重建完毕之后,进行一次不完全恢复,然后尝试直接open数据库,发现遇到如下错误:

这个错误也很常见。很多人都已经知道如何处理这种情况下,那就是推进SCN。那么这里如何推进scn呢?

由于该数据库是Oracle 10g,且没有安装最新的psu;因此我们可以直接使用oracle 10015 event来推进scn,命令如下:

alter session set events ‘10015 trace name adjust_scn level n’;

其中的n表示level,那么这个level应该是多少呢?应该是4*7=28,为了稳妥期间,我们一般设置比28稍微大一点,因此可以设置30.

经过10015 event的处理之后,再次open数据库,你会发现数据库已经open了,但是很快就会crash。因为会如下错误:

同一,该错误也太常见了。我们知道,对于ORA-00600 后面的错误编号,如果是在4000–6000的范围中,那么表示跟undo有关系。实际上我们之前dbv检查文件也确实发现undo有极少量的坏块存在。那么这里怎么处理这个问题呢?

既然undo存在文件,那么我们知道数据库在open的时候需要进行事务的rollback,而事务回滚则跟undo存在极大关系。那么这里我们可以通过几种方式来解决该问题:

1、通过undo_manangment=manual

2、._offline_rollback_segments

3、10513 event来禁止smon 进行事务恢复.

很明显,这里我选择第一种方式,更为简单,通过修改pfile即可很快解决该问题。通过参数修改很顺利打开了数据库,然后检查alert log发现会有如下类似的错误:

该错误,我相信不少同学都遇到过。从该错误的提示来看,就非常明确了,index key not found。也就是说这是index的问题。那么是什么对象呢? 也就是我们的obj# 5099。 对于object号大于56的,那么我们可以直接rebuild处理。

alert log中其实还有一些其他的错误,这里我们不在一一列举说明。前面已经提到过,由于cache丢失,那么数据库中的很多数据可能都不一致,如果通过修复alert log中的错误,然后提供业务运行,那么存在极大的风险。因此建议重建数据库比较好一些。

这里我们首先将undo进行重建处理,这样可以绕过很多错误,接着开始进行数据库重建工作。

补充:提供几篇文档供大家参考:

Step by step to resolve ORA-600 4194 4193 4197 on database crash (文档 ID 1428786.1)