oracle数据库块坏修复的一次经历

由于备份失误等各种原因,遇到了磁盘损坏的问题,导致数据库存储的数据文件有问题,从原来服务器上的数据文件拷贝出来也是有问题的。

拷贝的数据文件如下:

[root@ibopo-center-db seelinux]# ls
cms6_zgq_data.dbf  interact_data.dbf    zgq_wlwz_data.dbf  cms6_zgq_temp.dbf  interact_temp.dbf  wlkj_app_data.dbf   wlkj_app_temp.dbf   zgq_wlwz_temp.dbf

以及日志文件:

[root@ibopo-center-db orcl]# ls
control01.ctl  redo01.log  redo03.log    system01.dbf  system03.dbf  undotbs01.dbf
example01.dbf  redo02.log  sysaux01.dbf  system02.dbf  temp01.dbf    users01.dbf

文件都比较大,以上是从服务器硬盘上拷贝的数据,你只需要知道数据有损坏。

恢复的过程,遇到了各种各样的问题,毕竟是第一次遇到这种问题。
我先在新给的一台虚拟机上做实验,安装好oracle,建立一个相同的实例orcl,由于新的虚拟机上有相同的示例orcl,为了不影响实验,我先删除之前的orcl实例,就想刚安装好的oralce数据库一样。

切换到oracle 用户,su - oracle
使用dbca进行删除orcl实例。

dbca -silent -deleteDatabase -sourcedb orcl

使用dbca快速建立一个orcl的实例。

dbca -silent -createDatabase -templateName $ORACLE_HOME/assistants/dbca/templates/General_Purpose.dbc -gdbName orcl -sid orcl   -sysPassword huangbaokang -systemPassword huangbaokang -datafileDestination /u01/hbk/oraData -characterSet UTF8 -automaticMemoryManagement true

执行上述命令,在/u01/hbk/oraData会建立orcl实例的相关文件,并会自动启动oracle实例,所以要先关闭oracle,然后删除生成的所有文件,并把我们拷贝的数据文件和日志文件全部放回/u01/hbk/oraData/orcl目录下。

sql>shutdown immediate
[root@ibopo-center-db orcl]# cd /u01/hbk/oraData/orcl/
[root@ibopo-center-db orcl]# rm -rf *

使用scp也好,ftp也好,把文件放在该目录,放好之后,注意要改变用户所属组(chown oracle:oinstall *)。

[root@ibopo-center-db orcl]# cd /u01/hbk/oraData/orcl/
[root@ibopo-center-db orcl]# ll
总用量 83910456
-rw-r----- 1 oracle oinstall 10013908992 11月 23 16:29 cms6_zgq_data.dbf
-rw-r----- 1 oracle oinstall    30416896 11月 23 15:53 cms6_zgq_temp.dbf
-rw-r----- 1 oracle oinstall    10076160 11月 23 16:49 control01.ctl
-rw-r----- 1 oracle oinstall   104865792 11月 23 11:50 example01.dbf
-rw-r----- 1 oracle oinstall    52436992 11月 23 11:50 interact_data.dbf
-rw-r----- 1 oracle oinstall    30416896 11月 21 21:51 interact_temp.dbf
-rw-r----- 1 oracle oinstall   576724992 11月 23 16:29 lob_hbk_data.dbf
-rw-r----- 1 oracle oinstall  2147484160 11月 23 11:45 redo01.log
-rw-r----- 1 oracle oinstall  2147484160 11月 23 16:49 redo02.log
-rw-r----- 1 oracle oinstall  2147484160 11月 23 11:16 redo03.log
-rw-r----- 1 oracle oinstall  1111498752 11月 23 16:48 sysaux01.dbf
-rw-r----- 1 oracle oinstall 34319900672 11月 23 16:47 system01.dbf
-rw-r----- 1 oracle oinstall  4194312192 11月 23 11:50 system02.dbf
-rw-r----- 1 oracle oinstall 24536686592 11月 23 15:44 system03.dbf
-rw-r----- 1 oracle oinstall    30416896 11月 23 16:00 temp01.dbf
-rw-r----- 1 oracle oinstall  1782587392 11月 23 16:49 undotbs01.dbf
-rw-r----- 1 oracle oinstall     5251072 11月 23 11:50 users01.dbf
-rw-r----- 1 oracle oinstall  1939873792 11月 23 11:50 wlkj_app_data.dbf
-rw-r----- 1 oracle oinstall    30416896 11月 21 21:51 wlkj_app_temp.dbf
-rw-r----- 1 oracle oinstall   681582592 11月 23 11:50 zgq_wlwz_data.dbf
-rw-r----- 1 oracle oinstall    30416896 11月 23 11:26 zgq_wlwz_temp.dbf

接下来是进行数据库还原操作(recovery)

先启动到nomout阶段

sql>startup nomount

执行还原

sql>recover database

打开数据库

sql>alter database open;

再把相关表空间加上(这些过程其实就是通过重建控制文件使数据库启动,参考我的博客https://blog.csdn.net/huangbaokang/article/details/83992400)
以下可以从提供的博客的trc文件找到。

ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/hbk/oraData/orcl/temp01.dbf'
     SIZE 30408704  REUSE AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;
ALTER TABLESPACE CMS6_ZGQ_TEMP ADD TEMPFILE '/u01/hbk/oraData/orcl/cms6_zgq_temp.dbf'
     SIZE 30408704  REUSE AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;
ALTER TABLESPACE ZGQ_WLWZ_TEMP ADD TEMPFILE '/u01/hbk/oraData/orcl/zgq_wlwz_temp.dbf'
     SIZE 30408704  REUSE AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;
ALTER TABLESPACE WLKJ_APP_TEMP ADD TEMPFILE '/u01/hbk/oraData/orcl/wlkj_app_temp.dbf'
     SIZE 30408704  REUSE AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;
ALTER TABLESPACE INTERACT_TEMP ADD TEMPFILE '/u01/hbk/oraData/orcl/interact_temp.dbf'
     SIZE 30408704  REUSE AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;

经过这样恢复之后,使用exp导出报了如下错
在这里插入图片描述

依然是数据库坏损坏问题,当使用了exp导出,或者oracle自带的dbv检测工具,
通过以下语句,可以查询当前数据块已损坏

select * from v$database_block_corruption;

发现有一大堆的数据块损坏,根据文件号和块号,查询具体损坏信息

select tablespace_name,segment_type,owner,segment_name from dba_extents where file_id=6 and 939960 between block_id and block_id+blocks-1;

每一个块都这样去检查,汇总得到的情况,有TABLE类型的坏块,和INDEX类型的坏块,和LOBSEGMENT类型的坏块。
在这里插入图片描述
在这里插入图片描述

由于被修复好了,上面的图其实是当时遇到问题所截图,图片信息在此略。
针对索引类型的坏块,直接删除重建索引即可解决问题。针对表类型的坏块,使用10231事件,配合exp导出,再次删除原来的表,然后导入会原来的数据库,参考我的博客https://blog.csdn.net/huangbaokang/article/details/84031845

alter system set events='10231 trace name context forever,level 10';

但是遇到用10231事件解决不了TABLE类型的坏块,期间还遇到连imp都导了不了。期间遇到了如下错误
在这里插入图片描述

把db_recovery_file_dest_size调大。

SQL> show parameter db_recovery_file_dest_size
这里显示的是默认安装oracle的大小,调大到30G
SQL> alter system set db_recovery_file_dest_size=30G;
System altered.

期间还遇到检查点不能完成的问题。以下图片从其他网站拷贝的,只是描述类似的问题

在这里插入图片描述

然后我有学习了如何扩大redo.log的空间,当时我的是50M,不够,我给它加到2G.
参考我的博客https://blog.csdn.net/huangbaokang/article/details/84330685

具体用到的命令如下:

--select group#,members,bytes/1024/1024,status from v$log;
--select member from v$logfile;
--alter system switch logfile;
--alter system checkpoint;
--alter database add logfile group 3('/u01/hbk/oraData/orcl/redo03.log') size 2048M;
--alter database drop logfile group 5

通过扩大了redo表空间之后才顺利使用imp命令导入成功表了。
特难搞的是LOBSEGMENT类型的坏块,由于当时对LOB类型字段的表存储不是很了解,期间熬夜加班查看了大量的相关类型博客,了解到它的存储特征跟普通字段不一样。
期间使用空块的处理方式,最终解决了我的问题,博客参考
https://blog.csdn.net/sdulsj/article/details/52993052

相关命令:

--CREATE TABLE corr_rows (row_id ROWID,error_code NUMBER);

--CREATE TABLE corr_rows (row_id ROWID,error_code NUMBER);

--DECLARE
-- n           NUMBER;
-- ERROR_CODE NUMBER;
-- corr_rows  NUMBER := 0;
-- ora_1578  EXCEPTION;
-- PRAGMA    EXCEPTION_INIT(ora_1578,-1578);
--begin
-- for cursor_lob in (select rowid rid, title_pic
--                       FROM a_content_text) LOOP
--    begin
--      n := dbms_lob.instr(cursor_lob.title_pic, hextoraw('01234567'));--这里有的博客填889911,我没搞懂这里的值是啥意思
--    EXCEPTION
--      WHEN ora_1578 THEN
--        corr_rows := corr_rows + 1;
--        INSERT INTO corr_rows
--        VALUES
--          (cursor_lob.rid, 1578);
--        COMMIT;
--      WHEN OTHERS THEN
--        ERROR_CODE := SQLCODE;
--        corr_rows  := corr_rows + 1;
--        INSERT INTO corr_rows
--        VALUES
--          (cursor_lob.rid, ERROR_CODE);
--        COMMIT;
--    END;
-- END LOOP;
-- dbms_output.put_line('Corrupted rows: ' || corr_rows);
--END;
--/



--update  a_content_text
--      set title_pic = empty_blob() 
-- WHERE ROWID in( select row_id from corr_rows);

--commit

建立新的表空间进行LOB类型字段的存储。

create tablespace lob_hbk
logging
datafile '/u01/hbk/oraData/orcl/lob_hbk_data.dbf'
size 50m
autoextend on
next 50m maxsize 20480m
extent management local;
ALTER TABLE A_CONTENT_TEXT MOVE LOB("TITLE_PIC") STORE AS hbk (
tablespace "LOB_HBK"
ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10);

--重建索引
alter index A_CONTENT_TEXT_PK rebuild tablespace LOB_HBK

终于搞定了这个难题,写篇心得,挺有成就感的,当了会公司应急解决问题的功臣哈哈(有点自傲了^_^),希望老板年底给我多发点奖金哈哈,毕竟这个数据库平台有十几个网站在跑,要是没解决,相关的网站客户绝对是会给公司带来不好的印象。

猜你喜欢

转载自blog.csdn.net/huangbaokang/article/details/84401163