oracle无备份修复坏块

来源:互联网 发布:刘永伟 知行路桥 编辑:程序博客网 时间:2024/04/29 23:07

无备份坏块处理

数据库版本:9.2.0.5.0
 
平台:windows2003


 
下午接到通知以数据库出现坏块现象,无备份,应用无法正常使用,要予以解决
 

 

由于没有备份,无法恢复,只能采用跳过坏块方法,然后通过业务补数据。
 
首先要通知业务需要停服务,其次用PL/SQL登录把OPTCABLE表的sql导出来。
 
 
 
首先要查出坏块中的对象是什么 file_id为截图中文件号,and 为数据库的块号。
 
 
 
SQL> SELECT tablespace_name,segment_type, owner, segment_name FROM dba_extents WHERE file_id =82 AND 326677between block_id AND block_id + blocks - 1;
 
 
 
TABLESPACE_NAME    SEGME   OWNER  SEGMENT_NAME
 
------------------------------ ---------------------------
 
USERS               TABLE    GISTAR    OPTCABLE
 
 
 
然后需要查询数据对象的id(用于查询rowid的参数)
 
 
 
SQL> SELECT data_object_id FROMdba_objects WHERE object_name = 'OPTCABLE' and owner='GISTAR';
 
 
 
DATA_OBJECT_ID
 
--------------
 
        97248
 
 
 
找出坏块最小的rowid  (1, DATA_OBJECT_ID ,file_id,数据库的块号,0)
 
 
 
SQL> select dbms_rowid.rowid_create(1,97248,82,326677,0) from dual;
 
 
 
DBMS_ROWID.ROWID_C
 
------------------
 
AAAXvgABSAABPwVAAA
 
 
 
找出坏块最大的rowid  (1, DATA_OBJECT_ID ,file_id,数据库的块号+1,0)
 
 
 
SQL> select dbms_rowid.rowid_create(1,97248,82,326678,0) from dual;
 
 
 
DBMS_ROWID.ROWID_C
 
------------------
 
AAAXvgABSAABPwWAAA
 
 
 
然后通过rowid来确定坏块数据的范围,以便排除
 
这里要注意,rowid的取值一定要大于大的,小于小的(上步骤查询出来的2个rowid)
 
 
 
SQL> SELECT /*+ ROWID(A) */ COUNT(*)FROM OPTCABLE A WHERE ROWID>='AAAXvgABSAABPwWAAA';
 
 
 
当进行查询时又报出undo表空间也有坏块
 
ERROR 位于第 1 行:
 
ORA-01578: ORACLE 数据块损坏(文件号107,块号225)
 
ORA-01110: 数据文件 107:'D:\ORACLE\ORADATA\LNXC\UNDOTBS07.DBF'
 
 
 
解决此问题要替换undo表空间(注意未结束的回滚段)
 
 
 
create undo tablespace undo2 datafile'd:\oracle\oradata\lnxc\undo02_01.dbf' size 2048M;
 
 
 
alter system set undo_tablespace=undo2;
 
 
 
重启数据库后查询undo信息(undo已经更换)
 
 
 
SQL> show parameter undo;
 
 
 
NAME                                 TYPE        VALUE
 
----------------------------------------------- ------------------------------
 
undo_management                      string      AUTO
 
undo_retention                       integer     10800
 
undo_suppress_errors                 boolean     FALSE
 
undo_tablespace                      string      UNDO2
 
 
 
删除老undo表空间报错,发现了未结束的回滚段
 
 
 
SQL> drop tablespace UNDOTBS1 includingcontents and datafiles;
 
drop tablespace UNDOTBS1 including contentsand datafiles
 
*
 
ERROR 位于第 1 行:
 
ORA-01548: 已找到活动回退段'_SYSSMU5$',终止删除表空间
 
 
 
 
 
创建pfile

SQL> create pfile='d:\t.txt' fromspfile;
 
 
 
关闭实例
 
 
 
SQL> shutdown immediate
 
 
 
编辑pfile加入如下参数(注意,CORRUPTED_ROLLBACK_SEGMENTS中一定要包含未结束的回滚段)
 
 
 
*.undo_management='MANUAL'
 
*._CORRUPTED_ROLLBACK_SEGMENTS=(_SYSSMU5$,_SYSSMU6$,_SYSSMU7$,_SYSSMU8$,_SYSSMU9$,_SYSSMU10$)
 
 
 
用pfile启动数据库
 
 
 
SQL> startup pfile='d:\t.txt';
 
 
 
删除原来的undo表空间(数据文件也删除)
 
 
 
SQL> drop tablespace UNDOTBS1 includingcontents and datafiles;
 
 
 
再用spfile重启数据库,因为我们要用undo2表空间进行修复(不用指定参数文件,默认)
 
 
 
startup
 
 
 
查询undo段信息
 
 
 
SQL> selectsegment_name,status,tablespace_name from dba_rollback_segs;
 
 
 
SEGMENT_NAME         STATUS           TABLESPACE_NAME
 
-------------------- ----------------------------------------------
 
SYSTEM               ONLINE           SYSTEM
 
_SYSSMU17$           ONLINE           UNDO2
 
_SYSSMU18$           ONLINE           UNDO2
 
_SYSSMU19$           ONLINE           UNDO2
 
_SYSSMU20$           ONLINE           UNDO2
 
_SYSSMU21$           ONLINE           UNDO2
 
_SYSSMU22$           ONLINE           UNDO2
 
_SYSSMU23$           ONLINE           UNDO2
 
_SYSSMU24$           ONLINE           UNDO2
 
_SYSSMU25$           ONLINE           UNDO2
 
_SYSSMU26$           ONLINE           UNDO2
 
 
 
发现没有问题,切换生产用户,继续修复坏块
 
然后通过rowid来确定坏块数据的范围,以便排除
 
这里要注意,rowid的取值一定要大于大的,小于小的(上步骤查询出来的2个rowid)
 
 
 
SQL> SELECT /*+ ROWID(A) */ COUNT(*)FROM OPTCABLE A WHERE ROWID>='AAAXvgABSAABPwWAAA';
 
 
 
 COUNT(*)
 
----------
 
151362
 
 
 
SQL> SELECT /*+ ROWID(A) */ COUNT(*)FROM OPTCABLE A WHERE  ROWID<'AAAXvgABSAABPwVAAA';
 
 
 
 COUNT(*)
 
----------
 
    27699

 
 
以原表结构创建一个新表,用来存放该表完好的数据(rowid依然大于大的小于小的)
 
 
 
SQL> CREATE TABLE OPTCABLE_BAK AS SELECT/*+ ROWID(A) */ * FROM OPTCABLE A WHERE ROWID>='AAAXvgABSAABPwWAAA';
 
 
 
SQL> INSERT INTO  OPTCABLE_BAK SELECT /*+ ROWID(A) */ * FROMOPTCABLE A WHERE ROWID<'AAAXvgABSAABPwVAAA';
 
 
 
SQL> commit;
 
 
 
现在就把完好的数据成功找回,这里注意不要用rename的方式去修改表名让业务使用,因为新创建表字段的默认值已经丢失,还需要重新加默认值。
 
 
 
按照一开始用PL/SQL导出的表sql去重新创建表结构,非表对象等等。
 
 
 
然后重新插入数据
 
 
 
SQL> insert into optcable select * fromoptcable_bak;
 
 
 
SQL> commit;
 
 
 
删除创建的临时表(9i或9i以上没有开回收站的数据库不用加purge,其他建议加purge)
 
 
 
SQL> drop table optcable_bak;
 
 
 
SQL> drop table optcable_bak1;
 
 
 
到此坏块问题解决,如果11G版本还有统计信息的,建议追加统计信息。

0 0
原创粉丝点击