使用10046跟蹤Oracle前映象資料讀
“Undo前映象”是Oracle早期推出的特性之一,也是在諸多資料庫產品中異軍突起的致勝法寶。當我們在一個會話中啟動事務,對資料進行增加、修改和刪除操作的時候,只要沒有提交事務,其他會話只能看到資料的舊版本,也就是事務會話修改之前的版本。所以,在Oracle中,select操作不會阻塞任何操作,也不會被任何操作所阻塞。
1、Undo與前映象
這樣的特性就是依賴Oracle推出的Undo前映象機制。當我們開啟事務,修改一個資料塊的時候,Oracle首先會修改資料塊塊頭的ITL(事務槽)資訊,將當前事務資訊(xid事務標識)寫入到ITL中的一行。之後標記下這個事務對應的Undo空間地址。之後,才能進行資料塊的修改。
在修改資料塊的過程中,Oracle的Server Process會將資料塊的原有內容(對Update和Delete操作而言),儲存到Undo表空間上Undo段的位置上。
Undo段內容有很多的用途。當另外的會話需要訪問資料塊時,首先會去檢查資料塊的ITL事務槽資訊,檢視要訪問的資料塊是不是正在被修改。如果正在被修改,就根據ITL上面留下的事務槽資訊訪問Undo段。同時,如果只有一部分資料被修改,Oracle Server Process還要結合資料塊中未被修改的內容進行結果集合拼裝。
只有在事務正式完成,commit或者rollback之後,Undo段中的extent狀態才不再是Active。非Active狀態的Undo也有其價值,Oracle的“多版本一致讀”、“Flashback”等特性,都是基於對非Active狀態Undo的資料利用。
本篇,我們打算使用10046等待事件,監控一下Oracle是如何進行前映象讀取動作的。
2、實驗環境準備
我們選擇11gR2版本進行試驗。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for 32-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 – Production
建立實驗資料表T。
SQL> create table t as select * from dba_objects;
Table created
SQL> select object_id from dba_objects where wner='SYS' and object_name='T';
OBJECT_ID
----------
188217
SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where segment_name='T' and wner='SYS';
HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS
----------- ------------ ---------- ---------- ----------
1 89344 10485760 1280 25
對應分割槽資訊。
SQL> select extent_id, file_id, block_id, blocks from dba_extents where segment_name='T' and wner='SYS';
EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- ---------- ---------- ----------
0 1 89344 8
1 1 89352 8
2 1 89384 8
(篇幅原因,省略部分內容……)
22 1 94592 128
23 1 94720 128
24 1 95616 128
25 rows selected
系統當前採用自動化Undo管理。
SQL> show parameter undo;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
3、Trace檔案獲取
我們現在一個會話中,開啟事務刪除所有的資料。
SQL> select sid from v$mystat where rownum<2;
SID
----------
145
SQL> delete t;
84331 rows deleted
在另一個會話中,我們啟動實驗。注意,首選需要排除快取髒塊的影響,將髒塊寫入到資料檔案。
--另一個會話
SQL> select sid from v$mystat where rownum<2;
SID
----------
21
SQL> alter system checkpoint;
System altered
SQL> alter system flush shared_pool;
System altered
SQL> alter system flush buffer_cache;
System altered
SQL> select value from v$diag_info where name='Default Trace File';
VALUE
------------------------------------------------------------------------------
d:\app\bspdev\diag\rdbms\ora11gw\ora11gw\trace\ora11gw_ora_2208.trc
開啟跟蹤操作過程。
SQL> alter session set events '10046 trace name context forever, level 12';
會話已更改。
SQL> select count(*) from t;
COUNT(*)
----------
84331
SQL> alter session set events '10046 trace name context off';
會話已更改。
我們可以在指定目錄上找到對一個trace檔案ora11gw_ora_2208.trc。
4、結果分析
我們從trace原始檔案中,發現了比普通FTS(Full Table Scan)操作的不同。更多的操作細節和資源消耗。從直觀上感覺,進行select操作消耗更多的時間。
Trace檔案細節資訊。
=====================
PARSING IN CURSOR #3 len=22 dep=0 uid=0 ct=3 lid=0 tim=156068168118 hv=2763161912 ad='30303208' sqlid='cyzznbykb509s'
select count(*) from t
END OF STMT
PARSE #3:c=234375,e=1924863,p=525,cr=4754,cu=0,mis=1,r=0,dep=0,og=1,plh=2966233522,tim=156068168115
EXEC #3:c=0,e=43,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=2966233522,tim=156068168297
WAIT #3: nam='SQL*Net message to client' ela= 3 driver id=1413697536 #bytes=1 p3=0 obj#=188217 tim=156068168350
WAIT #3: nam='db file scattered read' ela= 14472 file#=1 block#=89345 blocks=3 obj#=188217 tim=156068182967
WAIT #3: nam='db file sequential read' ela= 14293 file#=3 block#=7522 blocks=1 obj#=0 tim=156068197389
WAIT #3: nam='db file sequential read' ela= 2580 file#=3 block#=7521 blocks=1 obj#=0 tim=156068200612
WAIT #3: nam='db file sequential read' ela= 2353 file#=3 block#=7520 blocks=1 obj#=0 tim=156068204231
WAIT #3: nam='db file sequential read' ela= 2355 file#=3 block#=7524 blocks=1 obj#=0 tim=156068207835
WAIT #3: nam='db file sequential read' ela= 2353 file#=3 block#=7523 blocks=1 obj#=0 tim=156068211050
WAIT #3: nam='db file sequential read' ela= 2352 file#=3 block#=7526 blocks=1 obj#=0 tim=156068215311
(省略部分內容……)
FETCH #3:c=2265625,e=11162122,p=3131,cr=87951,cu=0,mis=0,r=1,dep=0,og=1,plh=2966233522,tim=156079330523
STAT #3 id=1 cnt=1 pid=0 pos=1 bj=0 p='SORT AGGREGATE (cr=87951 pr=3131 pw=0 time=0 us)'
STAT #3 id=2 cnt=84331 pid=1 pos=1 bj=188217 p='TABLE ACCESS FULL T (cr=87951 pr=3131 pw=0 time=21345344 us cost=329 size=0 card=86741)'
WAIT #3: nam='SQL*Net message from client' ela= 785 driver id=1413697536 #bytes=1 p3=0 obj#=0 tim=156079331506
FETCH #3:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=2966233522,tim=156079331569
WAIT #3: nam='SQL*Net message to client' ela= 3 driver id=1413697536 #bytes=1 p3=0 obj#=0 tim=156079331615
*** 2013-02-18 08:20:42.187
WAIT #3: nam='SQL*Net message from client' ela= 43041122 driver id=1413697536 #bytes=1 p3=0 obj#=0 tim=156122372771
CLOSE #3:c=0,e=26,dep=0,type=0,tim=156122372940
=====================
系統操作消耗最大的部分,在於對資料塊的讀操作等待。從SQL的情況來看,Oracle只有全表掃描一條道路可以選擇。而Oracle進行FTS操作的過程我們是清晰的。
在之前的文章中,我們討論過FTS的操作過程。Oracle在進行FTS的時候,首先會從資料字典中定位資料頭塊位置,並且以單塊讀方式獲取到頭塊。在頭塊分析中,Server Process獲取到了資料段所有extents的分割槽資訊,包括起始頭塊位置和塊數量。之後根據這些資訊進行一系列的多塊讀操作。
但是從我們看到的raw結果,Oracle在反覆進行對file_id=1和file_id=3檔案塊的讀取。對1號檔案的讀取主要是多塊讀,但是大小遠遠小於我們的經驗值。對3號檔案完全是點讀動作,一次只會讀取一個資料塊。
下面我們擷取出一個片段進行分析。
WAIT #3: nam='db file scattered read' ela= 14472 file#=1 block#=89345 blocks=3 obj#=188217 tim=156068182967
WAIT #3: nam='db file sequential read' ela= 14293 file#=3 block#=7522 blocks=1 obj#=0 tim=156068197389
WAIT #3: nam='db file sequential read' ela= 2580 file#=3 block#=7521 blocks=1 obj#=0 tim=156068200612
WAIT #3: nam='db file sequential read' ela= 2353 file#=3 block#=7520 blocks=1 obj#=0 tim=156068204231
WAIT #3: nam='db file sequential read' ela= 2355 file#=3 block#=7524 blocks=1 obj#=0 tim=156068207835
WAIT #3: nam='db file sequential read' ela= 2353 file#=3 block#=7523 blocks=1 obj#=0 tim=156068211050
WAIT #3: nam='db file sequential read' ela= 2352 file#=3 block#=7526 blocks=1 obj#=0 tim=156068215311
WAIT #3: nam='db file sequential read' ela= 2467 file#=3 block#=7525 blocks=1 obj#=0 tim=156068218786
WAIT #3: nam='db file scattered read' ela= 6824 file#=1 block#=89349 blocks=3 obj#=188217 tim=156068229398
WAIT #3: nam='db file sequential read' ela= 2356 file#=3 block#=7531 blocks=1 obj#=0 tim=156068231844
WAIT #3: nam='db file sequential read' ela= 2457 file#=3 block#=7530 blocks=1 obj#=0 tim=156068234728
從標紅部分可以看到,Oracle首先到1號檔案讀取了3個資料塊,啟示塊號是89345。這個塊是什麼呢?
SQL> select owner, segment_name, EXTENT_ID, FILE_ID, BLOCK_ID, BLOCKS from dba_extents where file_id=1 and block_id<=89345 and block_id+blocks-1>89345;
OWNER SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- -------------------- ---------- ---------- ---------- ----------
SYS T 0 1 89344 8
顯然,這三個塊是資料表T第一個extent對應的分割槽資料塊。Oracle在讀取了之後,從ITL上知道了對應的Undo空間地址,就連續進行了7次對file_id=3的塊操作,而且每次都是一個資料塊。
我們隨機找一下一個塊的屬性。
SQL> select owner, segment_name, extent_id, file_id, block_id, blocks, status from dba_undo_extents where file_id=3 and block_id<=7522 and block_id+blocks-1>7522;
OWNER SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS STATUS
---------- -------------------- ---------- ---------- ---------- ---------- ---------
SYS _SYSSMU8_1557854099$ 21 3 7424 128 ACTIVE
很明顯,Oracle在讀了三個資料塊之後,非連續(隨機)的訪問了Undo段_SYSSMU8_1557854099$的第21分割槽中的一些資料塊。目的很明顯,就是獲取前映象,而且這些前映象是進行單塊讀操作。
當完成所有的前映象點塊讀之後,Oracle就可以合併出一致讀的結果集。之後,在進行下3個塊的讀取動作。
5、結論
從上面的實驗裡面,我們可以得到幾個想法。
首先,Oracle進行一致讀的時候,每次進行多塊讀,獲取的資料塊數量是相對較少的。一般來說,多塊讀的上限規模和作業系統IO能力、Oracle內部多塊讀引數有關。但是在例項中,一次只會讀出三塊,猜想與一致讀有關。
其次,在獲取到資料塊之後,Oracle會按照每個塊中ITL資訊,以單塊的方式“點讀”那些Undo塊。並且進行合併結果集操作。
最後,從10046結構看,一致讀是相當消耗資源的。在一致讀狀態下,檢索效能要受到幾個數量級別的影響。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-754233/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle 10046跟蹤的使用Oracle
- 使用oracle的10046事件跟蹤SQL語句Oracle事件SQL
- oracle sql跟蹤 event 10046 - 轉OracleSQL
- ORACLE 10046 設定跟蹤事件後無跟蹤檔案Oracle事件
- 使用10046跟蹤sql語句SQL
- oracle 跟蹤當前使用者會話Oracle會話
- Oracle資料庫跟蹤SQLOracle資料庫SQL
- 對使用dblink的10046事件跟蹤事件
- 10046 跟蹤其他會話會話
- 使用10046事件跟蹤分析執行計劃事件
- 【TRACE】如果通過10046跟蹤資料庫效能問題資料庫
- 10046事件跟蹤會話sql事件會話SQL
- 跟蹤資料庫的命令:event 10046等的設定(ZT)資料庫
- 使用10046 event trace跟蹤全表掃描操作
- 啟用跟蹤事件10046---06事件
- 跟蹤SQL - SQL Trace 及 10046 事件SQL事件
- 設定10046跟蹤處理資料庫不能open一例資料庫
- Oracle事件跟蹤及結構資料dumpOracle事件
- Oracle 跟蹤全部使用者Oracle
- oracle 跟蹤其他使用者Oracle
- Oracle 開啟10046跟蹤引起 $ORACLE_BASE 目錄空間暴漲Oracle
- 使用 Tkprof 分析 ORACLE 跟蹤檔案Oracle
- 使用dtrace跟蹤oracle函式呼叫Oracle函式
- 使用10046事件 +10704事件對索引線上重建的跟蹤事件索引
- ORACLE 跟蹤工具Oracle
- [zt] oracle跟蹤檔案與跟蹤事件Oracle事件
- oracle跟蹤檔案與跟蹤事件(zt)Oracle事件
- oracle跟蹤檔案和跟蹤事件(zt)Oracle事件
- 資料庫資料跟蹤記錄資料庫
- sql server跟蹤資料庫SQLServer資料庫
- 【最佳化】10046事件之生成跟蹤檔案事件
- 10046 跟蹤的trace檔案相關解釋
- 轉:使用 Tkprof 分析 ORACLE 跟蹤檔案Oracle
- 【TRACE】Oracle跟蹤事件Oracle事件
- Oracle跟蹤會話Oracle會話
- Oracle 跟蹤事件【轉】Oracle事件
- Oracle跟蹤檔案Oracle
- 清理Oracle資料庫大量的SYS使用者審計跟蹤檔案Oracle資料庫