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