Oracle数据库故障导致vCenter不能启动

作者: loaf 分类: Uncategorized 发布时间: 2013-08-14 13:26

VC Appliance停机是用待机方式将Oracle数据库停了。再启动时,Oracle不能启动。用SQLPLUS中的Starup命令。出现下面的提示:

由于ORA-03113错误是一个通用的错误提示,能给的信息量很少。
于是一步步的来Debug,由于startup相当于3个命令的集合,就一步步地执行
先执行
SQL>startup nomount
并没有发现什么明显的失败信息,说明启动数据库实例是没有问题的,再执行第二步
SQL>alter database mount;
出现故障

看来故障出现在挂载数据库文件时,这一步骤主要是“允许特定的维护操作, 例如, 重命名数据文件, 添加, 删除或重命名重做日志文件, 启用和禁用重做归档选项, 执行完全数据库恢复。它不允许对数据库进行一般的访问。”
找到$ORACLE_HOME/rdbms/log目录,用ls -ltr找到最近的日志文件。在本例中是sales_ora_27010.trc

看来是olr.loc和ocr.loc两个文件不能打开。但是我的机器上根本没有这个文件。在网上搜索,发现这两个文件和Oracle的集群有关,我这里是单节点的,按说是不需要Oracle Local Registry的。
在网上搜索,也没有什么特别有用的提示,但是发现了另一个问题,就是我找的日志文件可能不对,找了原来安装时导出的备份虚拟机,用命令

SQL>show parameter background

找到正确的日志路径/usr/local/oracle/diag/rdbms/oracle/sales/trace
查看启动时的日志,在最后发现

Starting ORACLE instance (normal)
LICENSE_MAX_SESSION = 0
LICENSE_SESSIONS_WARNING = 0
Picked latch-free SCN scheme 3
Using LOG_ARCHIVE_DEST_1 parameter default value as USE_DB_RECOVERY_FILE_DEST
Autotune of undo retention is turned on.
Wed Aug 07 15:37:46 2013
SMON started with pid=13, OS id=30687
Wed Aug 07 15:37:46 2013
RECO started with pid=14, OS id=30689
Wed Aug 07 15:37:46 2013
MMON started with pid=15, OS id=30691
starting up 1 dispatcher(s) for network address ‘(ADDRESS=(PARTIAL=YES)(PROTOCOL=TCP))’…
Wed Aug 07 15:37:46 2013
MMNL started with pid=16, OS id=30693
starting up 1 shared server(s) …
ORACLE_BASE from environment = /usr/local/oracle
Wed Aug 07 15:37:46 2013
ALTER DATABASE   MOUNT
USER (ospid: 30698): terminating the instance
Instance terminated by USER, pid = 30698

重试了多次,结果大多类似。在日志相同目录里,找到最近的trc文件,发现如下内容:

[root@localhost trace]# vi sales_ora_20498.trc
Release:        2.6.32-279.el6.x86_64
Version:        #1 SMP Fri Jun 22 12:19:21 UTC 2012
Machine:        x86_64
Instance name: sales
Redo thread mounted by this instance: 0 <none>
Oracle process number: 19
Unix process pid: 20498, image: oracle@localhost.localdomain (TNS V1-V3)
*** 2013-08-08 09:23:49.818
*** SESSION ID:(125.37) 2013-08-08 09:23:49.818
*** CLIENT ID:() 2013-08-08 09:23:49.818
*** SERVICE NAME:() 2013-08-08 09:23:49.818
*** MODULE NAME:(sqlplus@localhost.localdomain (TNS V1-V3)) 2013-08-08 09:23:49.818
*** ACTION NAME:() 2013-08-08 09:23:49.818
Error: kccpb_sanity_check_2
Control file sequence number mismatch!
fhcsq: 38637 bhcsq: 38638 cfn 0
*** 2013-08-08 09:23:49.819
USER (ospid: 20498): terminating the instance

从上面来看,是控制文件故障。
现在重建控制文件,先到日志文件中找到一个相关参数的例子,在alert_sales.log文件中找出
Create controlfile reuse set database “oracle”
MAXINSTANCES 8
MAXLOGHISTORY 1
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
Datafile
‘/usr/local/oradata/ora11g/ORA11G/oracle/system01.dbf’,
‘/usr/local/oradata/ora11g/ORA11G/oracle/sysaux01.dbf’,
‘/usr/local/oradata/ora11g/ORA11G/oracle/undotbs01.dbf’,
‘/usr/local/oradata/ora11g/ORA11G/oracle/users01.dbf’
LOGFILE GROUP 1 (‘/usr/local/oradata/ora11g/ORA11G/oracle/redo01.log’) SIZE 51200K,
GROUP 2 (‘/usr/local/oradata/ora11g/ORA11G/oracle/redo02.log’) SIZE 51200K,
GROUP 3 (‘/usr/local/oradata/ora11g/ORA11G/oracle/redo03.log’) SIZE 51200K RESETLOGS
WARNING: Default Temporary Tablespace not specified in CREATE DATABASE command
Default Temporary Tablespace will be necessary for a locally managed database in future release
Successful mount of redo thread 1, with mount id 1691519286
Completed: Create controlfile reuse set database “oracle”
然后,根据网上“如何获得创建控制文件脚本并创建脚本”一文中的脚本模板
STARTUP NOMOUNT
CREATE CONTROLFILE REUSE DATABASE “PRIMARY” NORESETLOGS  ARCHIVELOG
—  SET STANDBY TO MAXIMIZE PERFORMANCE
MAXLOGFILES 5
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 1
MAXLOGHISTORY 226
LOGFILE
GROUP 1 ‘/opt/oracle/oradata/primary/redo01.log’  SIZE 10M,
GROUP 2 ‘/opt/oracle/oradata/primary/redo02.log’  SIZE 10M,
GROUP 3 ‘/opt/oracle/oradata/primary/redo03.log’  SIZE 10M
— STANDBY LOGFILE
DATAFILE
‘/opt/oracle/oradata/primary/system01.dbf’,
‘/opt/oracle/oradata/primary/undotbs01.dbf’,
‘/opt/oracle/oradata/primary/users01.dbf’
CHARACTER SET ZHS16GBK
;
RECOVER DATABASE
ALTER SYSTEM ARCHIVE LOG ALL;
ALTER DATABASE OPEN;
ALTER TABLESPACE TEMP ADD TEMPFILE ‘/opt/oracle/oradata/primary/temp01.dbf’
SIZE 41943040  REUSE AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;
在SQL>下先运行startup nomount,然后直接将根据上面和日志中参数,定义下面的脚本直接粘贴到SQL>下
CREATE CONTROLFILE REUSE DATABASE “oracle” NORESETLOGS  ARCHIVELOG
—  SET STANDBY TO MAXIMIZE PERFORMANCE
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 1
LOGFILE
GROUP 1 ‘/usr/local/oradata/ora11g/ORA11G/oracle/redo01.log’  SIZE 51200K,
GROUP 2 ‘/usr/local/oradata/ora11g/ORA11G/oracle/redo02.log’  SIZE 51200K,
GROUP 3 ‘/usr/local/oradata/ora11g/ORA11G/oracle/redo03.log’  SIZE 51200K
— STANDBY LOGFILE
DATAFILE
‘/usr/local/oradata/ora11g/ORA11G/oracle/vpx01.dbf’,
–‘/usr/local/oradata/ora11g/ORA11G/oracle/temp01.dbf’,
‘/usr/local/oradata/ora11g/ORA11G/oracle/system01.dbf’,
‘/usr/local/oradata/ora11g/ORA11G/oracle/sysaux01.dbf’,
‘/usr/local/oradata/ora11g/ORA11G/oracle/undotbs01.dbf’,
‘/usr/local/oradata/ora11g/ORA11G/oracle/users01.dbf’
在上面脚本中,我重试了几次,一次是日志大小,我想改成10M,但是不成功,另一次是提示temp01.dbf不是有效的数据库文件,我只有把它注释掉了,只能参照网上的脚本,一步步运行
其中,最后一句
ALTER TABLESPACE TEMP ADD TEMPFILE ‘/usr/local/oradata/ora11g/ORA11G/oracle/temp01.dbf’ SIZE 20480K REUSE AUTOEXTEND ON NEXT 640K MAXSIZE UNLIMITED
我也是从日志文件中找出来的。
根据上面显示的结果,应该是恢复成功了。
先重启操作系统。再手工启动Oracle,一切正常,但是对应的VCSA却不能启动,用OEM进去看到有数据块错误
从图中可以看到,ORA-01578错误,出现文件损坏,Block是45953。
用dbv命令检查文件
[oracle@localhost ~]$ dbv FILE=’/usr/local/oradata/ora11g/ORA11G/oracle/vpx01.dbf’ BLOCKSIZE=8192
得到下面的结果:
从中可以看出,被标记会Corrupt的块有452个。
再查询是哪些损坏的哪些内容:
Select tablespace_name,segment_type,owner,segment_name From dba_extents Where file_id=5 and 45953 between block_id and block_id+blocks-1;
结果如下:
说明损坏的是LOBSEGMENT
用命令找到损坏的表名和列名
结果为:
select count(*) from VPXADMIN.VPX_RESOURCE_POOL;
发现这个表中只有8行数据。
ROWID                      ID
—————— ———-
AAASVcAAFAAACfjAAA          8
AAASVcAAFAAACfkAAB        523
AAASVcAAFAAACfkAAA        816
AAASVcAAFAAACfkAAC        826
AAASVcAAFAAACfkAAD        833
AAASVcAAFAAACfkAAE        839
AAASVcAAFAAACflAAB       1212
AAASVcAAFAAACfjAAC       1601
一行一行地试
select * from VPXADMIN.VPX_RESOURCE_POOL where id>1212;
发现ID=1212的这条记录是损坏的。
delete  from  VPXADMIN.VPX_RESOURCE_POOL where id=1212;
删除后,这个表可以正常地访问了,用DBV检查,结果没有什么不同。
shutdown immadiate数据库,提示没有Commit,看来删除并没有真正成功,于是在SQL命令行下,直接输入commit提交了修改。然后可以关闭数据库了。重启数据库DBV检查情况并无改观,说明这些还不够。
想了半天,也没有什么头绪,回到OEM页面中,在“可用 性”里面,选择了“执行恢复”,看看能不能将表空间VPX恢复到8月3日之前。
点了半天后,提示操作失败,同时VPX也脱机了,在图形界面中却怎么为无法联机。真是事情越搞越乱,好在问题并不复杂,在SQL环境下,执行
recover datafile 5
alter database datafile 5 online;
alter tablespace VPX online;
就可以联机了。
再回到原来的问题。
排查到现在,还有两个方向研究,一个是从vCenter服务器不能启动服务入手,查看日志,查看出错的地点和原因。一个还是从DBV出的错误结果入手。
先从DBV入手,在网上搜索到这篇文章,发现,可能根据DBV出的错误信息找到出错的文件和块,从而找到对应的表。
下面一部分的DBV 201错误块信息
DBV-00201: Block, DBA 21044390, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044391, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044393, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044394, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044395, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044397, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044398, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044399, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044401, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044402, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044403, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044406, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044407, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044410, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044411, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044412, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044414, marked corrupt for invalid redo application
DBV-00201: Block, DBA 21044415, marked corrupt for invalid redo application
根据最后的显示,应该有452个块,这里这是一部分,因为终端显示不完全。
拿最后一个来测试一下
select dbms_utility.data_block_address_file(21044415) from dual;
select dbms_utility.data_block_address_block(21044415) from dual;
结果是File为5,Block为72895。再用
Select tablespace_name,segment_type,owner,segment_name From dba_extents Where file_id=5 and 72895 between block_id and block_id+blocks-1;
得到Segment名为SYS_LOB0000075068C00059$$用
得到表名为VPX_HOST,列表为RESOURCE_INFO,测试一下:
这里又出现了一个块10309,用相同的方法找到是VPX_HOST表中的另一个列CAPABILITY,这种方法很明显能找到故障表,但是对于修复却帮助不大,因为数量太大,没有办法手工处理。
按上文中提到的修复方法先创一个表
create table corrupted_data (corrupted_rowid rowid);
然后,在SQL提示符下粘贴下面脚本代码,最后用/结束并运行。
set concat off
declare
error_1578 exception;
pragma exception_init(error_1578,-1578);
n number;
begin
for cursor_lob in (select rowid r, &&lob_column from &table_owner.&table_with_lob) loop
begin
n:=dbms_lob.instr(cursor_lob.&&lob_column,hextoraw(‘889911’));
exception
when error_1578 then
insert into corrupted_data values (cursor_lob.r);
commit;
end;
end loop;
end;
根据提示符,输入需要的各变量值,列名为RESOURCE_INFO,所有者VPXADMIN,表名为VPX_HOST。脚本会把有问题行的ROWID写到上表创建的表中。上面的代码中hextoraw(‘889911’)有点奇怪,不知道是什么意思,在上文最后到是提到了,原来这个值是随便写的,主要是让n总是返回0值。
然后再将有问题行中的对应列数据填为空值。
set concat off
update &table_owner.&table_with_lob set &lob_column=empty_blob() where rowid in (select corrupted_rowid from corrupted_data);
出现下面的错误提示
ORA-00932: inconsistent datatypes: expected NCLOB got BLOB
于是将上面的代码修改成
update &table_owner.&table_with_lob set &lob_column=empty_clob() where rowid in (select corrupted_rowid from corrupted_data);
回到命令行方式,用DBV再试一次,结果却仍是有452个Page被标记为坏。
但是这次用Select * from vpxadmin.vpx_host;能返回正常的值了。说明表的确是被修复了。但量DBV结果仍标记为Corrupted,用DBV来找坏表的实用性就差了许多。像这样有452个坏块,一个一个地测试,太麻烦了。
转到vCenter的服务器中,
发现在启动过程中,初始化VPXD时出错。
查看/var/log/vmware/vpx目录下的日志。大致可判断为数据库中数据读出来后,反序列化出错。但是因为上面的原因我又找到不出故障的表的内容,用OEM在表空间里试了几个表,都是好的,从VCenter日志中也找不出线索,问题就变成死问题了。
看来只能重建一个表空间给vCenter用,原来保留的数据也只有放弃了。