生產環境遭遇ORA-01410: invalid rowid。分析

wei-xh發表於2010-12-09

一個過程報錯:ORA-01410: invalid rowid。
這個過程以前都沒有出現過這個錯誤。當時正在rebuild online索引。懷疑是這個原因導致的。


錯誤模擬:
1)session1,建立一個表T1,ID為主鍵。執行一個比較耗時的SQL,強制讓這個SQL用上索引。
drop table t1;
create table t1 as  
select  
rownum  id,  
rpad(rownum,10) v1,  
rpad('x',100)   v2  
from  
all_objects  
where  
rownum <= 10000 ;
;  

alter table t1 add constraint t1_pk primary key(id);  
execute dbms_stats.gather_table_stats(user,'t1')  

   

declare
  m_v1 varchar2(10);
begin
  for r in (select /*+ index(t1) */
             v1
              from t1
             where id > 0) loop
    m_v1 := r.v1;
    dbms_lock.sleep(0.01);
  end loop;
end;
/

2)session2執行如下語句:
DROP TABLE ttt;
alter index t1_pk rebuild online;  
CREATE TABLE  ttt  AS  select * from dba_objects;

session2會很快完成,這個時候檢視session1,報錯了ORA-01410: invalid rowid。

解釋如下:
1)rebuild索引的時候,會現在一個臨時段去建立。建立完成後,會釋放老索引段的空間。比較權威的原話如下:
if you rebuild an index (whether or not you use the online option) Oracle will copy the index contents from one location to another and,
when the copy is complete, free up the space that held the original index contents.


2)如果你在rebulid之前執行了一個比較長的查詢,這查詢將繼續使用老索引。Oracle introduced a form. of ‘cross-DDL read consistency’ many years
ago to make partition maintenance operations possible, and that’s the feature that allows your query to carry on running.

3)那麼這種情況下怎麼辦呢?一個表需要擴充套件或者一個索引需要擴充套件或者一個新表需要建立,那麼老索引的空間就有可能被填充,那麼你之前的長查詢還在依賴這個
老索引空間,這種情況一出現,就有可能出現錯誤ORA-01410: invalid rowid。



如果實驗裡建立表TTT的表空間不跟索引T1_PK在一個表空間,就不會報錯。

不理解的再看下這篇文章:

打不開的用這個中轉一下:


[ 本帖最後由 wei-xh 於 2010-12-9 10:53 編輯 ]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22034023/viewspace-681330/,如需轉載,請註明出處,否則將追究法律責任。

相關文章