1. 程式人生 > >oracle資料庫塊壞修復的一次經歷

oracle資料庫塊壞修復的一次經歷

由於備份失誤等各種原因,遇到了磁碟損壞的問題,導致資料庫儲存的資料檔案有問題,從原來伺服器上的資料檔案拷貝出來也是有問題的。

拷貝的資料檔案如下:

[[email protected] 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

以及日誌檔案:

[[email protected]
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
[[email protected] orcl]# cd /u01/hbk/oraData/orcl/
[[email protected] orcl]# rm -rf *

使用scp也好,ftp也好,把檔案放在該目錄,放好之後,注意要改變使用者所屬組(chown oracle:oinstall *)。

[[email protected] orcl]# cd /u01/hbk/oraData/orcl/
[[email protected] 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

終於搞定了這個難題,寫篇心得,挺有成就感的,當了會公司應急解決問題的功臣哈哈(有點自傲了^_^),希望老闆年底給我多發點獎金哈哈,畢竟這個資料庫平臺有十幾個網站在跑,要是沒解決,相關的網站客戶絕對是會給公司帶來不好的印象。