一. 官網說明html
在MOS 上的一篇文章講到了rebuild online 和offline的區別:sql
Index Rebuild Is Hanging Or Taking Too Long [ID 272762.1]數據庫
Symptoms:
=========
Performance issues while rebuilding very large indexes. The offline rebuilds of their index is relatively quick -finishes in 15 minutes. Issuing index rebuild ONLINE statement => finishes in about an hour. This behavior of ONLINE index rebuilds makes it a non-option for large tables as it just takes too long to scan the table to rebuild the index. The offline may not be feasible due to due to the 24/7 nature of the database. This may be a loss of functionality for such situations. If we attempt to simultaneously ONLINE rebuild the same indexes we may encounter hanging behavior indefinitely (or more than 6 hours).
DIAGNOSTIC ANALYSIS:
--------------------
We can trace the sessions rebuilding the indexes with 10046 level 12. Comparing the IO reads for the index-rebuild and the index-rebuild-online reveals the following:
ONLINE index rebuilds: It scans the base table and it doesn't scan the blocks of the index.
OFFLINE index rebuilds:It scans the index for the build operation.session
This behaviour is across all versions.併發
Cause/Explanation
=============
When you rebuild index online, it will do a full table scan on the base table. At the same time it will maintain a journal table for DML data, which has changed during this index rebuilding operation. So it should take longer time, specially if you do lots of DML on the same table,while rebuilding index online.
-- rebuild index online的時候,會選擇全表掃描,同時會維護一箇中間日誌表,用來記錄在rebuild 期間的增量數據,原理相似於物化視圖日誌,日誌表是一個索引組織表(IOT),這張中間表只有插入,不會有刪除和修改操做,並且只有主鍵條件查詢,正是IOT最合適的場景。oracle
On the other hand, while rebuilding the index without online option, Oracle will grab the index in X-mode and rebuild a new index segment by selecting the data from the old index. So here we are not allowing any DML on the table hence there is no journal table involved and it is doing an index scan. Hence it will be pretty fast. less
--rebuild offline時,選擇的6模式的X 鎖,它根據old index 來rebuild。 所以不容許進行DML,也就沒有中間表。所以也比較塊。工具
Solution/Conclusion:
===========
- The ONLINE index rebuild reads the base table, and this is by design.
- Rebuilding index ONLINE is pretty slow.
- Rebuilding index offline is very fast, but it prevents any DML on the base table.post
二. rebuild index 說明ui
有關鎖的模式信息以下:
鎖模式 |
鎖描述 |
解釋 |
SQL操做 |
0 |
none |
||
1 |
NULL |
空 |
Select |
2 |
SS(Row-S) |
行級共享鎖,其餘對象只能查詢這些數據行 |
Select for update、Lock for update、Lock row share |
3 |
SX(Row-X) |
行級排它鎖,在提交前不容許作DML操做 |
Insert、Update、 Delete、Lock row share |
4 |
S(Share) |
共享鎖: 阻止其餘DML操做 |
Create index、Lock share |
5 |
SSX(S/Row-X) |
共享行級排它鎖:阻止其餘事務操做 |
Lock share row exclusive |
6 |
X(Exclusive) |
排它鎖:獨立訪問使用 |
Alter table、Drop able、Drop index、Truncate table 、Lock exclusive |
鎖 死鎖 阻塞 Latch 等待 詳解
http://blog.csdn.net/tianlesoftware/archive/2010/08/20/5822674.aspx
DML操做通常要加兩個鎖,一個是對錶加模式爲3的TM鎖,一個是對數據行的模式爲6的TX鎖。只要操做的不是同一行數據,是互不阻塞的。
在rebuild index online 的開始和結束階段時,須要短暫的對錶持有模式爲4的TM鎖的,當獲取到4級別的鎖以後,才降爲2級。若是rebuild online一直沒獲取到4級別的鎖,那麼相關的DML所有產生等待。 在執行期間只持有模式2的TM鎖,不會阻塞DML操做。 在Oracle 11g以後,oracle作了特殊處理,後續的dml不會被rebuild online的4級別鎖阻塞.
因此若是在執行rebuild index online前長事務,而且併發量比較大,則一旦執行alter index rebuild online,可能由於長事務阻塞,可能致使系統瞬間出現大量的鎖,對於壓力比較大的系統,這是一個不小的風險。這是須要迅速找出致使阻塞的會話kill掉,rebuild index online一旦執行,不可輕易中斷,不然可能遇到ORA-08104。
MOS 的文檔:
Session Was Killed During The Rebuild Of Index ORA-08104 [ID 375856.1]
While running an online index rebuild your session was killed or otherwise terminated abnormally. You are now attempting to run the index rebuild again and is throwing the error:
ORA-08104: this index object ##### is being online built or rebuilt
關於這個錯誤NiGoo 同窗的blog 有說明,連接以下:
http://www.ningoo.net/html/2007/dba_memo_online_rebuild_index_encounter_ora-08104.html
根據以上說明,咱們能夠知道在進行online rebuild 的時候,Oracle 會修改以下信息:
(1)修改ind$中索引的flags,將該flags+512. 關於這個flags的含義,在下面的實驗中進行說明。
(2)在該用戶下建立一個journal table 來保存在rebuild期間的增量數據。 該代表名稱: sys_journal_<object_id>.
若是異常結束online rebuild操做,那麼oracle就沒及時清理journal table和ind$的flags標誌位,系統會認爲online rebuild還在操做。
固然SMON 進程會來處理這些臨時段。 在maclean 同窗(10g,11g OCM)的Blog裏提到了功能:
瞭解你所不知道的SMON功能(一):清理臨時段
http://www.oracledatabase12g.com/archives/smon-cleanup-temporary-segment.html
對於永久表空間上的temporary segment,SMON會三分鐘清理一次(前提是接到post),若是SMON過於繁忙那麼可能temporary segment長期不被清理。temporary segment長期不被清理可能形成一個典型的問題是:在rebuild index online失敗後,後續執行的rebuild index命令要求以前產生的temporary segment已被cleanup,若是cleanup沒有完成那麼就須要一直等下去。
若是SMON 不能及時清理,在操做時就會報ORA-08104的錯誤。
在Oracle10gR2中可使用dbms_repair.online_index_clean手工清理這些信息,在Oracle 9i下,須要打Bug 3805539 後纔可使用該工具。
手工處理的步驟以下:
(1)先查看ind$ flags 標誌,若是不正確,就減去512.
sql>update ind$ set flags=flags-512 where obj#=<object id>;
(2)drop journal table,這個步驟可能會報資源忙,由於有大量的日誌正在插入,能夠反覆重試一下。
sql>drop table <owner>.sys_journal_<object_id>;
注意:
這個步驟不能反,若是先刪除sys_journal_<object_id>臨時表,而後再修改index的flags狀態,則會報出ora-600 [4610]號錯誤,即數據字典不一致的錯誤。
官網關於dbms_repair.online_index_clean 的說明:
This function performs a manual cleanup of failed or interrupted online index builds or rebuilds. This action is also performed periodically by SMON, regardless of user-initiated cleanup.
This function returns TRUE if all indexes specified were cleaned up and FALSE if one or more indexes could not be cleaned up.
DBMS_REPAIR.ONLINE_INDEX_CLEAN (
object_id IN BINARY_INTEGER DEFAULT ALL_INDEX_ID,
wait_for_lock IN BINARY_INTEGER DEFAULT LOCK_WAIT)
RETURN BOOLEAN;
Description |
|
object_id |
Object id of index to be cleaned up. The default cleans up all object ids that qualify. |
wait_for_lock |
This parameter specifies whether to try getting DML locks on underlying table [[sub]partition] object. The default retries up to an internal retry limit, after which the lock get will give up. If LOCK_NOWAIT is specified, then the lock get does not retry. |
所以在作rebuild index online的時候,必定要在開始和結束階段觀察系統中是否有長事務的存儲,對於併發量較大的系統,最嚴重的後果,可能在這兩個關鍵點致使數據庫產生大量鎖等待,系統負載飆升,甚至宕機。