6、ITL事物槽:
<a href="http://blog.csdn.net/changyanmanman/article/details/7081699">http://blog.csdn.net/changyanmanman/article/details/7081699</a>
更詳細的ITL事務槽的測試實驗參考我的部落格:
一個修改事務的開始執行:
1) 首先當一個事務開始時,需要在undo段事務表上配置設定一個事務表項;
2) 在資料塊頭部獲得一個ITL事務槽,該事務槽指向復原段段頭的事務表項;
3) 在修改資料之前,需要在復原段中記錄前鏡像資訊,復原段頭事務表項指向該記錄;
4) 鎖定修改行,修改行鎖定位(lb-lock block)指向ITL事務槽;
5) 資料修改可以進行
7、分析undo:
這是我對biti大師的博文復原段了解一文閱讀總結,僅供自己複習使用。
我們可以說undo復原段是用來儲存資料變化前映像而提供一緻讀和保障事務完整性的一段磁盤存儲區域。這個定義很學術化,我們大概知道復原段是在磁盤上的一段空間,當一個事務開始的時候,會首先把變化前的資料和變化後的資料先寫入日志緩沖區,然後把變化前的資料寫入復原段,最後才在資料緩沖區中修改資料(日志緩沖區内容在滿足一定的條件後可能被寫入磁盤,但在事務送出的時候日志必須寫入磁盤,而資料緩沖區中資料依賴于檢查點的發生和DBWR程序的活動,在這裡不繼續讨論相關内容)。舉個例子,當我們做如下操作:
SQL> update t set object_id = '0' where object_id = '12344';
1 row updated.
SQL>commit;
Commit complete.
這時資料庫首先把該語句的整個操作包括資料’0’和’12344’寫入日志緩沖區(我覺着至少是首先用server
process 程序把資料塊從磁盤讀入資料緩沖區,然後在把要修改的資料提取到日志緩沖區中),然後把資料’12344’和一些相關資訊寫入復原段,最後把’0’修改到資料緩沖區。
當發出送出指令的時候,如果日志緩沖區内容還沒有寫入日志檔案則必須寫進日志檔案,復原段把該事務标記為已經送出,資料緩沖區中塊的這些事務也标記為已經送出(在大事務的情況下如果資料緩沖區中塊已經被寫入磁盤或者該事務更改的塊超過資料緩沖區總大小的10%則不再對這些塊标志該事務為已經送出,這會影響到我們下次讀該塊)。當然如果我們回退這個事務,則資料庫将把復原段中資料’12344’讀出來寫回資料緩沖區(資料緩沖區已經被修改為’0’),這個回退的變化本身也被寫入日志,這就是回退的過程。我們可以看出如果事務很大、資料緩沖區中事務資料如果已經被寫入磁盤了,那這簡直就是一個代價極其昂貴的操作。是以通常來說,我們認為一個系統中的事務的回退率應該比較低,否則應該檢查系統是否正常或者程式設計思路是否存在問題。我們可以通過下面查詢來衡量資料庫啟動以來的事務回退率,如果發現transaction
rollbacks/( transaction rollbacks + user commits)太高一定要引起重視。
SQL> select name,value from v$sysstat where name in ('user commits','transaction rollbacks');
NAME VALUE
-------------------------- ----------
user commits 12532
transaction rollbacks 21
SQL>
這裡我們介紹一下一緻性讀取,英文是consistent reads。對于oracle而言,查詢的結果集是根據時間點來判定的。Oracle内部通過系統改變号SCN作為相對時間點的标準,任何對資料庫的改變都會産生SCN,這個一個正整數,對資料塊的資料改變的時候會把該改變所對應的SCN記錄在塊中。假設查詢開始的時候的SCN為T,則在查詢所掃描的資料塊中,如果資料的COMMIT SCN小于T,則查詢接受該資料,如果COMMIT
SCN大于T或者說還沒有産生COMMIT SCN,則查詢會嘗試去復原段中查找資料。這是為了保證資料的讀取的時間點的一緻性,是以叫一緻性讀。
在通過復原段中擷取資料的時候,本質上是把資料緩沖區中資料塊做一份拷貝,然後将復原段中記錄的内容恢複到該塊中,然後查詢使用這個塊來進行讀取。這樣的塊的數量,如果大家有興趣可以通過SYS使用者登陸到資料庫然後查詢獲得
SQL> select count(*) from x$bh where state = 3;
COUNT(*)
----------
15
我們很可能産生這樣的困惑,復原段的塊是否存在于SGA中?如果有存在那為何不見有參數設定?
真實情況是,復原段的塊跟其他資料檔案的塊一樣,都在SGA中,也都是資料緩沖區中的一份子。同樣地,對于oracle8以上的版本的資料庫,我們可以通過查詢x$bh來确定復原段所占的塊的多少。我們可以參考v$rollstat視圖和x$bh表,在x$bh中的class字段,如果是復原段塊,假設復原段USN為n,則復原段頭class為11+2n,復原段塊為12+2n。我們來看看實際的例子
SQL> select usn from v$rollstat;
USN
----------
1
2
3
4
5
6
7
9
9 rows selected.
從復原段編号中我們可以看到編号8的復原段已經被删除了,總共9個復原段。
SQL> select class,count(*) from x$bh where class > 10 group by class;
CLASS COUNT(*)
---------- ----------
11 1
12 2
13 1
14 1
15 1
16 1
17 1
18 982
19 1
20 1
21 1
22 1
23 1
24 1
25 1
26 1
29 1
30 1
18 rows selected.
從這裡我們可以看出,復原段編号為8的class應該為27、28的塊是沒有。
復原段頭始終都是一個塊,class=18(usn=3)的復原段使用的塊比較多,是因為我的資料庫剛啟動,剛才執行了下面的語句。
SQL> delete from t;
25374 rows deleted.
commit;
Commit complete.
復原段的配置設定和使用
當事務産生的時候,資料庫會給事務配置設定一個復原段。當然我們可以指定事務使用某個復原段。在我的測試用的資料庫中,有如下復原段
select SEGMENT_ID ,SEGMENT_NAME from dba_rollback_segs;
SEGMENT_ID SEGMENT_NAME
---------- ------------------------------
0 SYSTEM
1 RBS0
2 RBS1
3 RBS2
4 RBS3
5 RBS4
6 RBS5
7 RBS6
9 RBS12
如果我們要指定事務使用某個復原段,如下
SQL> set transaction use rollback segment rbs6;
Transaction set.
SQL> insert into t select * from all_objects;
25649 rows created.
如果我們不認為的指定使用哪個復原段,則資料庫會根據復原段中事務來權衡,以使得所有復原段中事務壓力盡可能平均。我們考慮存在非系統復原段的情況(這也是絕大多數系統的情況,除非因為DBA嚴重錯誤才會使得系統隻存在系統復原段),在這種情況下我們發出的事務不會去使用系統復原段,這時系統復原段隻用于系統級使用,比如create、drop、truncate等發生的時候的系統級的資料字典的復原記錄。資料庫為我們發出的事務選擇非系統復原段,同一個事務不能跨越復原段,也就是說即使其他復原段還很空閑,該大事務也隻能使用被配置設定的復原段即使該復原段擴充。
接下來我們來考究單個復原段内的使用、擴充、回縮的問題。一個復原段至少包含2個extent。每個復原段有一個復原段頭,復原段頭是一個block,裡面主要記錄了事務表資訊。當産生一個事務的時候,就在復原段頭的事務表中記錄一條資訊,該資訊中包含了事務标志、事務狀态、使用的復原段塊數等等資訊。我們假定新建立的一個復原段存在extent
1,2,3,4,5。當第一個事務配置設定到復原段中的時候,除了事務表資訊,該事務從extent 1的第二個block開始使用,該事務送出後陸續不斷的事務到來并送出,假設我們已經使用到了extent 5的末尾。這時再來事務内容需要寫入,則重新使用extent 1 的第二個block。這樣循環使用復原段空間。同理復原段頭的事務表也是如此循環使用。循環的次數,可以通過如下查詢獲得
SQL> select usn,WRAPS from v$rollstat;
USN WRAPS
0 0
1 15
2 15
3 15
4 15
5 12
6 15
7 17
9 12
那麼我們會有一個問題,那就是既然復原段是循環使用的,那為什麼會擴充呢?注意在上面的例子中,所有的事務都是迅速送出了的。那我們現在假定這樣一種情況,存在一個事務,假設在extent 3 中有一個事務一直沒有送出,然後復原段一直循環使用到了extent 2。當extent 2使用完畢的時候發現extent 3中存在未送出事務,這是即使extent 4,5,1中的事務都已經送出,目前事務也不能越過extent 3而去使用後面的可使用的extent,這時該復原段就擴充新的extent,假定為extent
2-1。在資料庫中實際上復原段的extent之間是通過指針連起來的一個單向循環的連結清單結構。擴充的時候相當于在連結清單中插入一個節點extent 2-1,但節點2-1的下一個extent依然是 extent 3,假如2-1使用完畢發現extent 3仍然存在未送出事務復原段會繼續擴充。
我們做個例子,在SQLPLUS 1 中運作不送出(我們在v$rollstat 和 dba_rollback_segs中分别查詢發現usn =5的復原段對應了名字 rbs4)
SQL> select a.usn,b.segment_name from v$rollstat a,dba_rollback_segs b
2 where a.usn = b.segment_id;
USN SEGMENT_NAME
---------- --------------------------
0 SYSTEM
1 RBS0
2 RBS1
3 RBS2
4 RBS3
5 RBS4
6 RBS5
7 RBS6
9 RBS12
select usn,rssize "rollback segment size" from v$rollstat where usn = 5;
USN rollback segment size
---------- ---------------------
5 4186112
SQL> set transaction use rollback segment rbs4;
SQL> update t_small set object_id = 1;
100 rows updated.
打開SQLPLUS 2運作
begin
for i in 1..1000 loop
set transaction use rollback segment rbs4;
update t set object_id = i where rownum < 101;
end loop;
end;
SQL> select usn,rssize "rollback segment size" from v$rollstat where usn = 5;
USN rollback segment size
---------- ---------------------
5 55042048
現在我們來看在一個獨立的session中運作下面的查詢并對比查詢前後的復原段變化。
SQL> select usn,rssize "rollback segment size" from v$rollstat where usn= 4;
USN rollback segment size
---------- ---------------------
4 4186112
SQL> begin
2 for i in 1..1000 loop
3 set transaction use rollback segment rbs3;
4 update t set object_id = i where rownum < 101;
5 commit;
6 end loop;
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> select usn,rssize "rollback segment size" from v$rollstat where usn= 4;
4 4186112
在這兩個例子中我們很明顯地看到了復原段是否擴充的對比。那麼,做完第二個例子後,我再回過頭來查詢原來擴充的比較大的復原段,發現又變成4M了
SQL> select usn,rssize "rollback segment size" from v$rollstat where usn= 5;
USN rollback segment size
--------- ---------------------
5 4186112
復原段在擴充後,是要回縮的。假設復原段目前extent n,使用完畢将準備使用extent n+1 的時候(extent n+1 無活動事務),如果設定了optimal并且復原段大于 optimal設定的大小,檢查extent n+2 中是否有未送出事務,如果沒有,則回收extent n+2,本質上,就是在復原段的連結清單上摘去extent n+2 ,然後繼續檢查extent n+3 決定是否回收,由此重複該動作。Optimal設定決定了復原段最終回收後的大小,復原段回縮後大小盡可能的接近optimal設定。如上面例子是4M,可通過下面查詢(shrinks表示復原段回縮的次數,實際上v$rollstat提供了很多的復原段資訊,大家可以參考oracle
document)
SQL> select USN,OPTSIZE,SHRINKS from v$rollstat;
USN OPTSIZE SHRINKS
---------- ---------- ----------
0 0
1 4194304 0
2 4194304 0
3 4194304 0
4 4194304 0
5 4194304 10
6 4194304 0
7 4194304 0
9 0
系統復原段與延遲復原段
SYSTEM 復原段是建立在系統表空間中,主要是用于系統級的事務和配置設定普通事務于其他復原段上。當手工建立資料庫後需要建立普通復原段之前必須首先建立系統復原段。按照oracle文檔說明,當普通事務異常多的事情可能會出現使用系統復原段的情況。但正常情況下,系統復原段主要用于兩個方面。
一是系統事務,比如針對資料字典的操作的truncate table 和 drop table 。如果truncate table or drop table 的過程中沒有成功,則系統會根據系統復原段中的資料字典操作資訊對該DDL操作進行回退。
另一個方面,就是延遲復原段(Deferred Rollback Segment)。延遲復原段表示的是,當我們使一個表空間OFFLINE(exeample: alter tablespace users offline)之後,由于表空間不可用(不能進行讀寫),這個時候若有事務資料位于該表空間并且執行了復原指令,復原完成将顯示給client,對于client看起來該事務已經復原,但是對于資料庫來說該復原并沒有真正完成,這個時候資料庫将該復原資訊寫入系統復原段(這就是延遲復原段),等表空間重新ONLINE的時候,資料庫從系統復原段中将復原資訊寫入表空間。
復原段的設定和管理
事實上,對于作為個人意見來說,復原段的管理本不應該是作為DBA的複雜的任務來對待的,因為復原段的管理本來就可以使其很簡單。幾乎所有的系統出現復原段問題,不外乎都是復原段大小不足、復原段個數太少。9i以前的版本因為對于我們來說,無非也就是這兩個問題。
關于復原段表空間大小、復原段資料檔案的擴充、復原段的擴充等建立時指定的參數問題,我想參考建立文法就足夠了,沒有必要在這上去糾纏max extents是100還是200,你會發現去考慮這些參數沒有實質上的意義了。所有的一切設定,我隻需要問幾個問題就足夠了:
1:系統并發事務數有多少?
2:系統是否存在大查詢或者大是事務?頻繁麼?
3:能提供給系統的復原段表空間的磁盤空間是多少?
在初始化參數檔案中存在參數transactions_per_rollback_segment和transactions,共同決定了執行個體啟動的時候将嘗試聯機的最大復原段個數,transactions決定了同時存在的最大事務數。在這裡順便提及的2個初始化參數
max_rollback_segments 系統允許的最大復原段個數
rollback_segments 該參數是一個參數清單,假如建立復原段的時候是PUBLIC類型,則跟該參數無關,假如是PRIVATE類型的,則必須使得復原段出現在該參數清單裡面,否則資料庫啟動之後這些復原段不會自動聯機(可手動)。在OPS/RAC中,PUBLIC類型的復原段表示所有的INSTANCE都可以聯機這些復原段(但同一時刻隻能有一個執行個體聯機),相當于是一個公共復原段池。
在執行個體啟動的時候,執行個體嘗試聯機rollback_segments中設定的復原段,直到達到個數為min(CEIL(transactions/transactions_per_rollback_segment), max_rollback_segments)。若沒有達到這個值,則執行個體嘗試在PUBLIC類型的復原段池中嘗試聯機復原段,直到達到該值或者不再有復原段可聯機。
當一個執行個體啟動後其聯機復原段的個數是否足夠,跟并發事務數有關,若每個復原段上活動事務過多可能導緻嚴重的復原段争用。
這裡說了問題一相關内容,我們再看後面兩個問題。由于復原段的擴充和回收是昂貴代價的操作,通常我們是要避免的。如果存在大的查詢,就算不會去寫復原段,但是由于一緻讀,我們也可以參照前面内容,知道如果這期間事務繁忙復原段被循環使用覆寫過,可能出現著名的ORA-01555錯誤。又由于事務産生的時候除非人為指定使用哪個復原段,否則事務使用哪個復原段對于我們應用來說是透明的,同時我們能指定事務使用哪個復原段但并不能阻止别的事務不使用某個復原段,這樣我們就必須認識到,復原段設定成大小不一緻是不合适的,幾乎是沒有意義的,因為瓶頸總是決定于最小的一個復原段(這類似于木桶原理,決定裝水量的多少是由最短的片所決定的)。是以我們應該統一復原段的大小。那通常對于一個系統來說,幾百M的磁盤空間甚至幾G的磁盤空間根本不是問題,是以我們沒有理由在這裡研究復原段到底是使用4M大小還是10M大小,我們根據能提供的磁盤空間的估計,完全可以設定復原段為50M/100M甚至更大的大小,這主要決定于在大查詢運作期間每個復原段上可能的事務生成量,以及單個事務可能産生的復原資料的大小。假如系統偶爾存在批量作業的時候可能使得某個復原段擴充到1G,但平常我們的復原段大小在50M就不會出現回縮現象。那這個特定的時候如果資料庫不繁忙隻有大作業我們可以建立幾個很大的復原段,然後是其他復原段offline,等批作業完成然後再online其他復原段,使大復原段offline。當然可能的話也可以指定批作業使用大的復原段。或者,我們可以為所有復原段設定optimal為50M,任其特定時刻擴充然後回縮(注意所有復原段的optimal必須設定一樣大小)。
對于復原段除了按照我們對系統狀況估計進行建立、删除外,還有使復原段聯機和脫機,我們要注意的是如果復原段處于聯機并且裡面有活動事務的時候,若想使復原段脫機(offline),則這時復原段處于一種懸置的狀态,也就是新的事務将不能使用該復原段,而原有的事務繼續存在,等待復原段中所有事務完畢後,復原段成為脫機狀态。
l 9i的UNDO TABLESPACE
從oracle9i 開始,推薦使用UNDO TABLESPACE,讓系統自動管理復原段。
SQL> show parameters undo
NAME TYPE VALUE
------------------------------------ ------- -------------
undo_management string AUTO
undo_retention integer 10800
undo_suppress_errors Boolean FALSE
undo_tablespace string UNDOTBS1
初始化參數undo_management 決定資料庫使用的復原段是否使用自動管理模式。AUTO表示自動管理,MANUAL表示手工管理,也就是跟8i中一樣。undo_tablespace指定在自動管理模式下INSTANCE使用哪個表空間,undo_retention表示在自動管理模式下,復原段中的資料在被覆寫前保留多長的時間,機關是秒。這個參數應該決定于系統所中一些大查詢運作的時間長度,以避免ORA-01555錯誤。當然,實際上由于9i提供的flashback功能,可根據需要決定該參數設定的時間長度。設定undo_retention的同時要估計這樣長的時間内系統所産生的復原資料的大小,結合硬體所提供的磁盤空間來綜合考慮。undo_suppress_errors參數如果設定為true在自動管理模式下,如果我們嘗試在建立復原段,則不傳回錯誤資訊,但實際上是無效的,設定為false則嘗試建立復原段會傳回錯誤資訊。
復原段成為了自動管理,一方面驗證了前面所說的復原段的管理的問題本不是一個複雜的問題,另一方面,自動管理讓我們覺得無所适從,幾乎人為的難以控制它了。比如UNDO表空間變的很大,我們卻不能縮小。這個時候我們可以考慮建立新的UNDO表空間,然後換到新的表空間,這時即使UNDO表空間中有事務也可以切換,隻不過不能立即删除該表空間,切換之後等到原來的表空間中的所有事務處理完畢并且達到undo_retention所限定時間之後,就可以drop原來的UNDO表空間。這樣可以解決UNDO表空間變的太大而無法縮小的問題。指令如下:
SQL> alter system set undo_tablespace = undotbs1;
System altered.
這裡要注意若切換了UNDO表空間後應該修改pfile或者spfile使得下次啟動應用新的UNDO表空間。
在自動管理模式下的UNDO表空間中的復原段的個數是變化的,裡面復原段依然存在着聯機和脫機的狀況,隻不過是系統自己管理。若在脫機的時候復原段中還存在着活動事務,這時也出現前面所講的一種懸置的狀态。這個時候系統可能會為此而生成提示資訊的trace檔案,這是沒有關系的,對系統沒有影響。
在9i下建立非自動管理的復原段而不使用UNDO 表空間,則設定undo_management為MANUAL,然後在系統表空間中建立一個復原段(注意這是必須的),建立自己的復原段表空間,這時可以在復原段表空間中建立復原段,建立完畢删除系統表空間中的復原段。
順便提及幾點,UNDO表空間在做含有LOB類型資料的EXP的時候如果資料量過大(也許是超過5G)可能出現BUG,ORACLE9.2.中如果UNDO是ASSM,若設定undo_retention不當等因素導緻擴充過大,也會出現BUG,導緻系統崩潰隻能進行媒體恢複。當然,建議管理生産資料庫的DBA們有空多浏覽metalink,了解各種版本的特性和BUG。
l 復原段著名的ORA-01555問題
關于一緻性讀前面已經有介紹,但是這裡我們不得不産生一個疑問,一緻讀擷取的時候發現復原段已經被覆寫而出現找不着變化前映像,也就是當COMMIT SCN大于T查詢嘗試去復原段中找回資料卻發現復原段已經被覆寫了(因為復原段是循環使用的),則會出現著名的ORA-01555錯誤。
另外一種情況是關于塊清除(block cleanout),這涉及到oracle的一個塊清除(block cleanout)的概念,也就是說已經送出的資料,需要标志為已經送出,進而使得後面的會話通路該資料的時候不再産生一緻讀而直接讀該塊。而如果事務送出的時候塊已經被寫入磁盤,則當時不會對塊進行清除,需要延遲清除(delay block cleanout)。當被送出但沒有來得及标志為送出的塊在下次被會話讀取的時候會話會檢查該塊上最新的事務狀态是否是活動的,如果已經不是活動的則修改事務标志。這樣做一次後就不再産生不必要的一緻讀。但這種情況僅僅出現在:事務很大可能産生這種情況,事務早已送出,復原段已經被覆寫,塊中沒有被标記是否送出,而目前查詢 SCN T也比目前復原段中記錄的最小的SCN小(查詢已經運作較長時間復原段都已經被覆寫)。這個時候資料庫不能判定目前查詢的SCN
T 與該塊的COMMIT SCN之間的大小關系,于是傳回了錯誤。事實上後面這種情況是罕見的,而了解起來也比較困難一些。通常我們可以不考慮這種情況。
當然上面是從資料庫角度來描述,從應用角度來确診這個問題,有幾種可能:
1:查詢執行時間太長。那麼在這個時候我們首先要做的工作就是優化查詢,然後是考慮能否把查詢放在資料庫不繁忙的時候運作,最後才是考慮加大復原段。
2:過度頻繁的送出。假如可以成批送出的事務,我們可能是單條送出了,應該考慮對整個處理一起送出,或者說分段送出而不是單條送出。
3:exp的時候使用了consistent = y。這個參數主要是為了保證在exp的時候使得所有導出來的表在時間點上具有一緻性,可避免存在主外鍵關系的表由于不同表時間點的不一緻而破壞了資料的完整性。建議該操作在系統空閑的時候進行。
4:由于復原段回縮導緻復原段還沒有循環使用的情況下就出現了在復原段中找不着資料的情況,那這隻能是加大復原段增大optimal設定。
其他諸如復原段不能擴充等等一目了然的原因,不再累述。
l 復原段的監控和一些有用script
對于復原段的監控,其實最通常的是檢視v$rollstat動态視圖
SQL> desc v$rollstat
Name Null? Type
----------------------------------------- -------- -------------------
USN NUMBER
EXTENTS NUMBER
RSSIZE NUMBER
WRITES NUMBER
XACTS NUMBER
GETS NUMBER
WAITS NUMBER
OPTSIZE NUMBER
HWMSIZE NUMBER
SHRINKS NUMBER
WRAPS NUMBER
EXTENDS NUMBER
AVESHRINK NUMBER
AVEACTIVE NUMBER
STATUS VARCHAR2(15)
CUREXT NUMBER
CURBLK NUMBER
另外一個幫助我們診斷問題的view
SQL> select * from v$waitstat;
CLASS COUNT TIME
------------------ ---------- ----------
data block 341 0
sort block 0 0
save undo block 0 0
segment header 0 0
save undo header 0 0
free list 0 0
extent map 0 0
bitmap block 0 0
bitmap index block 0 0
unused 0 0
system undo header 0 0
system undo block 0 0
undo header 4 0
undo block 81 0
14 rows selected.
從這個view中可以看出復原段頭和復原段塊的争用,如果嚴重也可以考慮增加復原段個數和增大復原段大小
現在給出一些有用的script
下面這個script是對于系統中存在着鎖等待的時候查詢到底是什麼session阻塞了别人。(注意在oracle9.2.0版本中提供了dba_blockers表顯示鎖住其他session的session的資訊,而dba_waiters則顯示了被鎖住的session的資訊)
SQL> select username,
2 v$lock.sid,
3 trunc(id1/power(2,16)) rbs,
4 bitand(id1,to_number('ffff','xxxx'))+0 slot,
5 id2 seq,
6 lmode,
7 request
8 from v$lock,v$session
9 where v$lock.type='TX'
10 and v$lock.sid = v$session.sid
11 and v$session.username = user;
USERNAME SID RBS SLOT SEQ LMODE REQUEST
------------------------------ ---------- ---------- ---------- ---------- ---------- ----------
RAINY 8 7 45 300 0 6
RAINY 13 7 45 300 6 0
從這裡我們可以看到是LMODE=6的阻塞了LMODE=0的session(LMODE=6表示session擁有鎖,鎖的類型是6,表示獨占)。
在$ORACLE_HOME/RDBMS/ADMIN目錄下有一個名為utllockt.sql的script,提供了詳細的說明,該script輸出一個很直覺的資料格式。
另外再介紹一個怎樣查詢資料庫目前某個session的事務所使用的復原段大小
SQL> select b.sid,
2 a.XIDUSN ,
3 a.USED_UBLK
4 from v$transaction a,v$session b
5 where a.addr = b.TADDR;
SID XIDUSN USED_UBLK
---------- ---------- ----------
8 1 3
ORACLE9.2.0版本提供的表内容如下, HOLDING_SESSION與WAITING_SESSION均表示SID,可根據v$session結合查詢資訊
SQL> desc dba_blockers
Name Null? Type
----------------------- -------- ----------------
HOLDING_SESSION NUMBER
SQL> desc dba_waiters
WAITING_SESSION NUMBER
LOCK_TYPE VARCHAR2(26)
MODE_HELD VARCHAR2(40)
MODE_REQUESTED VARCHAR2(40)
LOCK_ID1 NUMBER
LOCK_ID2 NUMBER
當然,事實上,還可以結合v$session中SQL_ADDRESS、SQL_HASH_VALUE聯合v$sqlarea,進而知道session正在運作什麼sql,通過v$lock、dba_objects、v$locked_object查詢有什麼鎖,鎖住了什麼對象。隻要你了解了oracle這些view的内容,所謂這些查詢就變成跟普通應用中查詢的需求一樣,解決問題不過是信手拈來的事情。
<a href="http://www.34hap.com/database/undoredo/oracle_undo_allocat.html">http://www.34hap.com/database/undoredo/oracle_undo_allocat.html</a>