當前位置:
首頁 > 知識 > ORACLE 如何檢查找出損壞索引

ORACLE 如何檢查找出損壞索引

(點擊

上方公眾號

,可快速關注)




來源:瀟湘隱者 ,


www.cnblogs.com/kerrycode/p/9645605.html




在Oracle資料庫中如何找出損壞索引呢? 下面我們人為構造一個案例,將索引塊損壞。如下案例所示:





SQL> create tablespace test_data 


  2  datafile  "/u01/app/oracle/oradata/gsp/test_data_01.dbf"


  3  size 200M autoextend off


  4  logging


  5  segment space management auto


  6  extent management local;


  


Tablespace created.


  


SQL> create tablespace test_index 


  2  datafile  "/u01/app/oracle/oradata/gsp/test_idx_01.dbf"


  3  size 200M autoextend off


  4  logging


  5  segment space management auto


  6  extent management local;


  


Tablespace created.


  


  


SQL> create user kerry


  2  identified by 123456


  3  default tablespace test_data;


  


User created.


  


SQL> grant connect to kerry;


SQL> grant resource to kerry;




上述腳本是創建表空間,創建用戶kerry並授權,然後使用kerry賬號登錄資料庫,構造測試數據,在TEST表上創建索引IX_TEST





SQL> show user;


USER is "KERRY"


SQL> 


SQL> CREATE TABLE TEST(ID  NUMBER(10), NAME VARCHAR2(64));


  


Table created.


  


SQL> DECLARE I  NUMBER;


  2  BEGIN


  3    FOR I IN 1..1000 LOOP


  4      INSERT INTO TEST VALUES(I, LPAD("T", 60));  


  5     END LOOP;


  6  COMMIT;


  7  END;


  8  /


  


PL/SQL procedure successfully completed.


  


  


SQL> CREATE INDEX IX_TEST ON KERRY.TEST(NAME) TABLESPACE TEST_INDEX;


  


Index created.




然後使用下面腳本找到索引段資料庫文件ID,以及索引段的第一個塊的塊號。





SQL> show user;


USER is "SYS"


SQL> col segment_name for a32;                               


SQL> col header_file for 9999;                               


SQL> col header_block for 9999;                              


SQL> select segment_name                                     


  2   ,header_file                                      


  3   ,header_block                                     


  4   ,blocks                                           


  5  from dba_segments ds                                    


  6  where ds.owner="KERRY" and ds.segment_name="IX_TEST";   


  


SEGMENT_NAME                     HEADER_FILE HEADER_BLOCK     BLOCKS


-------------------------------- ----------- ------------ ----------


IX_TEST                                    8          130         16


  


SQL>




構造壞塊的方法有不少(例如BBED等),這裡我們使用RMAN下面的命令clear,可以標記數據塊為corrupt,標記數據文件8中130號數據塊為壞塊。





[oracle@DB-Server ~]$ rman target /


  


Recovery Manager: Release 11.2.0.1.0 - Production on Thu Sep 13 17:41:05 2018


  


Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.


  


connected to target database: GSP (DBID=644393201)


  


RMAN> recover datafile 8 block 130 clear;


  


Starting recover at 13-SEP-18


using target database control file instead of recovery catalog


allocated channel: ORA_DISK_1


channel ORA_DISK_1: SID=12 device type=DISK


Finished recover at 13-SEP-18


  


RMAN>




那麼我們先來看看使用那些方法驗證索引損壞了,測試驗證一下看看是否可行。 




1:使用ANALYZE分析驗證索引結構





[oracle@DB-Server ~]$ sqlplus / as sysdba


  


SQL*Plus: Release 11.2.0.1.0 Production on Thu Sep 13 17:42:03 2018


  


Copyright (c) 1982, 2009, Oracle.  All rights reserved.


  


  


Connected to:


Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production


With the Partitioning, OLAP, Data Mining and Real Application Testing options


  


SQL> analyze index kerry.ix_test validate structure;


analyze index kerry.ix_test validate structure


*


ERROR at line 1:


ORA-01578: ORACLE data block corrupted (file # 8, block # 130)


ORA-01110: data file 8: "/u01/app/oracle/oradata/gsp/test_idx_01.dbf"







如上截圖所示,如果索引損壞(Corrupt Index),那麼使用analyze index validate structure就會報錯。要檢查整個資料庫所有的損壞索引(Corrupt Indexes)的話,就可以藉助下面腳本: 





spool analy_index.sql


SET PAGESIZE 50000;


SELECT


   "ANALYZE INDEX  " || OWNER || "." || INDEX_NAME|| " VALIDATE STRUCTURE;" FROM DBA_INDEXES;


  


spool off;


  


@analy_index.sql




2:使用系統視圖v$database_block_corruption查看損壞索引




如下所示,我們使用這個腳本來查看出現壞塊的索引,發現這個腳本無法找出壞塊索引。





set pagesize 50 linesize 170


col segment_name format a30


col partition_name format a30


SELECT DISTINCT file#, 


       segment_name, 


       segment_type, 


       tablespace_name, 


       partition_name 


FROM   dba_extents a, 


       v$database_block_corruption b 


WHERE  a.file_id = b.file# 


       AND a.block_id <= b.block# 


       AND a.block_id + a.blocks >= b.block#;







原因分析如下,視圖v$database_block_corruption中有壞塊記錄,但是我們將索引段的第一個塊標記為壞塊後,在dba_extents中沒有該索引段的記錄了。所以這種情況下的索引損壞,這個SQL語句根本無法找出壞塊索引。





SQL> SELECT file_id, 


  2         segment_name, 


  3         segment_type 


  4  FROM   dba_extents 


  5  WHERE  file_id = 8 ;


  


no rows selected


  


SQL> SELECT file_id, 


  2         segment_name, 


  3         segment_type 


  4 FROM   dba_extents 


  5  WHERE  owner = "KERRY";


  


   FILE_ID SEGMENT_NAME                     SEGMENT_TYPE


---------- -------------------------------- ------------------


         7 TEST                             TABLE


         7 TEST                             TABLE


 SQL>




因為一個段的第一個區的第一個塊是FIRST LEVEL BITMAP BLOCK,第二個塊是SECOND LEVEL BITMAP BLOCK,這兩個塊是用來管理free block的,第三個塊是PAGETABLE SEGMENT HEADER,這個塊才是segment里的HEADER_BLOCK,再後面的塊就是用來記錄數據的。關於這些知識,可以參考我博客ORACLE關於段的HEADER_BLOCK的一點淺析。而我們最上面的例子,是將第一個塊構造為壞塊,所以導致上面SQL無法查出。 我們重新構造案例,如我們將索引段的數據塊構造為壞塊,例如下面,將塊號148人為構造壞塊。那麼此時這個腳本就能找出壞塊索引了。所以綜上述實驗可以看出,這個腳本查找壞塊索引是有條件的,要看索引段損壞的塊是什麼類型





SQL> SELECT FILE_ID, 


  2         BLOCK_ID, 


  3         BLOCKS 


FROM   DBA_EXTENTS 


  4    5  WHERE  OWNER ="&OWNER"


  6       AND SEGMENT_NAME = "&TABLE_NAME"; 


Enter value for owner: KERRY


old   5: WHERE  OWNER ="&OWNER"


new   5: WHERE  OWNER ="KERRY"


Enter value for table_name: IX_TEST


old   6:      AND SEGMENT_NAME = "&TABLE_NAME"


new   6:      AND SEGMENT_NAME = "IX_TEST"


  


   FILE_ID   BLOCK_ID     BLOCKS


---------- ---------- ----------


         8        144          8


         8        152          8


  


SQL> SELECT HEADER_FILE


  2       , HEADER_BLOCK


  3       , BYTES


  4       , BLOCKS


  5       , EXTENTS 


FROM DBA_SEGMENTS 


  6    7  WHERE OWNER="&OWNER" AND SEGMENT_NAME="&SEGMENT_NAME";


Enter value for owner: KERRY


Enter value for segment_name: IX_TEST


old   7: WHERE OWNER="&OWNER" AND SEGMENT_NAME="&SEGMENT_NAME"


new   7: WHERE OWNER="KERRY" AND SEGMENT_NAME="IX_TEST"


  


HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS


----------- ------------ ---------- ---------- ----------


   8    146   131072   16   2


  


SQL>




RMAN> recover datafile 8 block 148 clear;




【關於投稿】




如果大家有原創好文投稿,請直接給公號發送留言。




① 留言格式:


【投稿】+《 文章標題》+ 文章鏈接

② 示例:


【投稿】《不要自稱是程序員,我十多年的 IT 職場總結》:http://blog.jobbole.com/94148/

③ 最後請附上您的個人簡介哈~






看完本文有收穫?請轉發分享給更多人


關注「ImportNew」,提升Java技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ImportNew 的精彩文章:

SpringBoot | 第二十章:非同步開發之非同步請求
SpringBoot | 第十六章:web 應用開發

TAG:ImportNew |