亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何進行ITL與事務處理

發布時間:2021-11-12 09:18:37 來源:億速云 閱讀:225 作者:柒染 欄目:關系型數據庫

如何進行ITL與事務處理,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

一、ITL與事務的關系

ITLinterested transaction list)事務槽是Oracle數據塊內部的一個組成部分,位于數據塊頭(block header)。ITLxidubaflaglckSCN/fsc組成,用來記錄在該數據塊上所有發生的事務。一個ITL槽位可以看作是一條事務記錄,它是Oracle中事務處理的關鍵組件,如果事務已經提交,則該ITL槽位就可以被反復使用,如果一直不提交,則該ITL槽位一直被占用,里面記錄著事務信息、回滾段入口、事務類型等。事務提交后,ITL槽位中仍保存著該事務提交時的SCN號。

ITL最小值為1,由參數initrans控制(由于兼容性的原因,Oracle會在對象的存儲塊上分配兩個ITL,因此inittrans的最小值實際上為2),這也是在建表時如果不指定initrans參數時的默認取值,最大值為255,由參數maxtrans控制,最大值參數在Oracle 10g以后不能被修改。一個ITL占用塊46B的空間,當塊中還有一定的free space時,Oracle可以使用free space構建ITL供事務使用,如果沒有了free space,則塊因為不能分配新的ITL就可能發生ITL等待。

當用戶發出一條SQL語句時,Oracle會記錄下這個時刻的SCN,然后在buffer cache中查找需要的block,或者從磁盤上讀取,當別的會話修改了數據,或者正在修改數據,就會在相應的block上記錄ITL,此時Oracle發現ITL中記錄的SCN大于select時刻的SCN,那么Oracle就會根據ITL中記錄的uba找到undo信息,獲得該block的前鏡像,然后在buffer cache中構造CRconsistent read )塊,此時Oracle也會檢查構造出來的blockITL記錄的SCN,如果SCN仍然大于select時刻的SCN,那么將繼續重復構造前鏡像,直到前鏡像blockITL記錄的SCN小于select時刻的SCN,同時檢查該事務是否提交或回滾,如果沒有,還要繼續構造前鏡像,直到找到需要的block。如果在構造前鏡像過程中所需的undo信息被覆蓋了,就會報快照過舊的錯誤。于是Oracle實現了多版本控制,這就是Oracle多版本的本質,這也就是為什么發出一條select語句時總是會看到consistent gets了。

二、ITL等待

發生ITL等待的場景有以下兩種情況:

1、超過了maxtrans配置的最大ITL數;

2initrans配置不足,且沒有足夠的free space開擴展ITL

解決辦法:

maxtrans不足:高并發引起,同一數據塊上的事務量已經超出了允許的ITL數量。因此需要減少事務的并發量,對于長事務,在保證數據完整性的前提下,增加commit的頻率,將長事務變為短事務,以減少資源占用。

initrans不足:數據塊上的ITL數量并沒有達到maxtrans的限制,發生這種情況的表通常是被較多的update,造成預留空間pctfree(默認10%)被填滿。此時可增加表的initranspctfree來解決,如果該表上事務的并發量高,可優先增加initrans,增大ITL槽位的初始分配量,反之,則優先增加pctfree,提升ITL槽位的擴展能力。

注意:如果是通過alter table方式修改了表的這兩個參數,那么只會影響新的數據塊,而不會改變已有數據的數據塊。

三、實驗驗證ITL與事務的關系

連接到scott用戶

sqlplus scott/tiger

創建測試表,pctfree設為0

create table t1(a number, b varchar2(30)) pctfree 0;

begin

    for i in 1 .. 1000 loop

        insert into t1 values (i, 'data');

    end loop;

    commit;

end;

/

查看段的區間分配信息

col segment_name for a20

col tablespace_name for a20

select segment_name, segment_type, tablespace_name, extent_id, file_id, block_id, blocks, bytes from dba_extents where owner = 'SCOTT' and segment_name = 'T1';

SEGMENT_NAME         SEGMENT_TYPE       TABLESPACE_NAME       EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS      BYTES

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

T1                   TABLE              USERS                         0          4        168          8      65536

查看塊分配信息

select distinct dbms_rowid.rowid_block_number(rowid) from scott.t1;

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

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

                                 171

                                 174

由此可知,t1表的數據占用了兩個數據塊,塊編號分別為171174t1段的第一個區間的起始編號為168,該區間由8個數據塊組成。

下面在同一個數據塊171上同時執行多個事務,看看到底會發生什么。

session1

update scott.t1 set b = 'Oracle data' where a <= 10;

已更新10行。

session2

update scott.t1 set b = 'Oracle data' where a > 10 and a <= 20;

已更新10行。

session3

先確定當前會話的sid

select sid from v$mystat where rownum = 1;

       SID

----------

       136

update scott.t1 set b = 'Oracle data' where a > 20 and a <= 30;

操作被hang住,事務處于等待狀態。

查看會話的等待事件

col event for a30

select sid, event, seconds_in_wait, state from v$session_wait where sid = 136;

       SID EVENT                          SECONDS_IN_WAIT STATE

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

       136 enq: TX - allocate ITL entry               242 WAITING

此時出現了分配ITL條目的等待。因為默認的初始ITL槽位分配為2,而pctfree0,兩個事務不提交,block中就沒有足夠空間分配ITL了,因此出現了會話被hang住一直在等待ITL的分配。前面的會話提交或回滾后,后面的會話才得以執行。

四、ITL進一步研究

當一個事務完成時,Oracle需要執行塊清理(block cleanout),清理掉這些在數據塊上的事務數據,清除ITL中的標志位、行中row header中的標志位等。塊清理分為兩種:fast commit block cleanoutdeferred block cleanout

快速提交塊清理(fast commit block cleanout):這是Oracle的默認行為。

延遲塊清理(deferred block cleanout):事務提交時,Oracle僅簡單的更新相關回滾段的頭部信息,而把數據塊的清理操作留給后來需要讀寫這個數據塊的操作者(之后的事務)。

設想一個update大量數據的操作,因為執行時間較長,一部分已修改的塊已被緩沖池flush out寫至磁盤,當update操作完成執行commit操作時,為進行塊清理,需要將那些已經寫至磁盤的數據塊重新讀入,這將消耗大量I/O,并使commit操作十分緩慢。為解決這個問題,Oracle使用了延遲塊清理的方案,對待存在以下情況的塊,commit操作不做塊清理:

1、在更新過程中,被緩沖池flush out寫至磁盤的塊;

2、當更新操作涉及的塊超過了塊緩沖區緩存的10%時,超出部分的塊。

雖然commit放棄對這些塊的清理,但仍會修改回滾段的段頭,回滾段的段頭包括了段中的事務信息,commit操作將本事務轉化為非active狀態。

當下一次操作如selectupdateinsertdelete訪問到這些塊時再來完成對塊的清理,這稱之為延遲塊清理。塊延遲清除通過事務槽上的回滾段號、槽號等信息訪問回滾段頭的事務信息,若事務不再活躍或事務過期則完成塊清理。塊延遲清除的影響在select操作過程中體現的最為明顯,這也是select語句產生redo信息的主要原因。

繼續前面的案例,先執行一個更新啟動一個新的事務,然后查詢出此更新涉及的數據塊,然后dump該數據塊的內容,進一步驗證ITL的信息。

執行更新

update scott.t1 set b = 'Oracle data' where a = 100;

確定更新所在的文件號和塊號

select dbms_rowid.rowid_relative_fno(rowid) from scott.t1 where a = 100;

DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID)

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

                                   4

select dbms_rowid.rowid_block_number(rowid) from scott.t1 where a = 100;

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

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

                                 171

開啟會話跟蹤

alter session set sql_trace=true;

oradebug setmypid

oradebug tracefile_name

c:\oracle\diag\rdbms\mes\mes\trace\mes_ora_3852.trc

dump數據塊

alter system dump datafile 4 block 171;

查看跟蹤文件c:\oracle\diag\rdbms\mes\mes\trace\mes_ora_3852.trc,可以看到關于ITL的信息:

Block header dump:  0x010000ab

 Object id on Block? Y

 seg/obj: 0x12458  csc: 0x00.1eb08d  itc: 2  flg: E  typ: 1 - DATA

     brn: 0  bdba: 0x10000a8 ver: 0x01 opc: 0

     inc: 0  exflg: 0

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0007.015.0000040c  0x00c00618.017a.07  C-U-    0  scn 0x0000.001ea944

0x02   0x0006.00e.000004ee  0x00c011d1.014e.1e  ----    1  fsc 0x0002.00000000

flag:事務狀態標志,占用塊中的一個字節,對應于v$transaction視圖中的status字段,意義如下:

----transaction is active or committed pending cleanout

c---transaction has been committed and locks cleaned out

--u-transaction committedmaybe long ago),SCN is an upper bound

-b--this undo record contains the undo for this ITL entry

---ttransaction was still active at block cleanout SCN

SCN/fsc:該ITL對應的事務提交時的SCN,那么這里所有槽位上最大的一個SCN號就表示這個block最后被更新時的SCN。每一個事務對應一個ITL記錄,如果該事務沒有涉及延遲塊清理,那么顯示的是fsc,如果是延遲塊清理,那么顯示的就是SCN

lck:事務鎖影響的記錄數。

對照視圖v$transaction,獲取此處update操作對應的事務信息

select xidusn, xidslot, xidsqn, ubafil, ubablk, ubasqn, ubarec from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN     UBAREC

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

         6         14       1262          3       4561        334         30

xid:其構成是xidusn.xidslot.xidsqn,三部分信息分別表示

xidusnundo segment number 回滾段號

xidslotslot number 事務槽號

xidsqnsequence number 序列號

uba:其構成是dba.ubasqn.ubarec,而dba包含了ubafilubablk的信息,分解如下

select dbms_utility.data_block_address_file(to_number('00c011d1', 'xxxxxxxx')) ubafil, dbms_utility.data_block_address_block(to_number('00c011d1', 'xxxxxxxx')) ubablk from dual;

    UBAFIL     UBABLK

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

         3       4561

ubafilundo block addressuba filenum 回滾塊地址 - 文件號

ubablkundo block number 回滾塊地址 - 塊號

ubasqnuba sequence number 回滾塊地址 - 序列號

ubarecuba record number 回滾塊地址 - 記錄號

于是根據uba信息,可以從回滾段的數據塊中找到該項事務的回滾信息,為此可以dump回滾段的數據塊

alter system dump datafile 3 block 4561;

查看跟蹤文件信息,找到該事務對應的回滾信息

UNDO BLK: 

xid: 0x0006.00e.000004ee  seq: 0x14e cnt: 0x1e  irb: 0x1e  icl: 0x0   flg: 0x0000

這里的seq即序列號ubasqncnt即記錄號ubarec。由rec #0x1e可以進一步在trace文件中找到update前的回滾信息

* Rec #0x1e  slt: 0x0e  objn: 74840(0x00012458)  objd: 74840  tblspc: 4(0x00000004)

*       Layer:  11 (Row)   opc: 1   rci 0x1d  

Undo type:  Regular undo   Last buffer split:  No

Temp Object:  No

Tablespace Undo:  No

rdba: 0x00000000

*-----------------------------

KDO undo record:

KTB Redo

op: 0x02  ver: 0x01 

compat bit: 4 (post-11) padding: 0

op: C  uba: 0x00c011d1.014e.1c

KDO Op code: ORP row dependencies Disabled

  xtype: XA flags: 0x00000000  bdba: 0x010000ab  hdba: 0x010000aa

itli: 2  ispac: 0  maxfr: 4858

tabn: 0 slot: 99(0x63) size/delt: 11

fb: --H-FL-- lb: 0x2  cc: 2

null: --

col  0: [ 2]  c2 02

col  1: [ 4]  64 61 74 61

fb:行標記,H表示head of rowFL分別表示行的first piecelast piece,說明此行涉及導出的數據塊,不存在行鏈接,又由于塊中存在行頭,說明也存在行遷移。

lbITL事務槽編號

cc:列的數量

回滾前的編碼是64 61 74 61,轉換為原始字符信息

select chr(to_number(64, 'xx')) || chr(to_number(61, 'xx')) || chr(to_number(74, 'xx')) || chr(to_number(61, 'xx')) undo_data from dual;

UNDO_DAT

--------

data

以上測試可見,Oracle是通過數據塊中的ITL信息來找到事務對應的回滾信息,同時實現了事務的讀一致性。如果事務已完成,ITL就可以被重用。

五、ITL與CR塊

Oracle的鎖管理是一種輕量級的鎖定機制,不是通過構建鎖列表來進行數據鎖定管理的,而是直接將鎖作為數據塊的屬性存儲在數據塊頭部,通過ITL實現。一個事務要修改塊中的數據,必須獲得改塊中的一個ITL(通過initrans預先分配的或者是通過pctfree space后來構建的),通過ITLundo segment header中的transaction table,可以知道事務處于活動階段還是已經完成。事務在修改塊時會檢查row header中的標志位,如果該標志位為0(該行沒有被活動的事務鎖住,這是可能要進行延遲塊清除等工作),就把該標志位修改為事務在該塊獲得的ITL序號,這樣當前事務就獲得了對記錄的鎖定,然后就可以修改行數據了。與此同時,在該事務處理過程中,如果有會話查詢該數據塊中的數據,Oracle就會讀取回滾段中的內容來構造保障數據讀一致性的CRconsistent read)塊。

在多用戶并發環境下,一個數據塊可以有多個CR版本,Oracle會在下列情況下構造數據塊的CR版本:

1、如果一個數據塊上有鎖,而有會話需要讀取這個數據塊中的內容,Oracle就會構造該數據塊的CR版本;

2、是否需要構造CR塊,與SCN密切相關。如果一個查詢游標對應的SCN小于數據塊當前的SCN,此時Oracle需要構造對應查詢游標SCNCR塊。

以下看一下數據塊及其不同版本的例子,操作分別在幾個不同會話中進行。

session1

查出表中數據所在的文件號和塊號

select distinct dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from scott.emp;

     FILE#     BLOCK#

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

   4             151

由文件號和塊號查詢緩存中的數據塊,此時還沒有該數據塊信息

select file#, block#, status, dirty, objd, ts# from v$bh where file# = 4 and block# = 151;

未選定行

對數據做查詢操作

select * from scott.emp;

緩存中產生了數據塊的xcur版本

select file#, block#, status, dirty, objd, ts# from v$bh where file# = 4 and block# = 151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 xcur       N      73196          4

刷新緩存

alter system flush buffer_cache;

緩存中的數據塊沒有消失,但狀態變為了free版本

select file#, block#, status, dirty, objd, ts# from v$bh where file# = 4 and block# = 151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 free       N      73196          4

對數據再次做查詢操作

select * from scott.emp;

查詢緩存塊,此時多了一個xcur版本

select file#, block#, status, dirty, objd, ts# from v$bh where file#=4 and block#=151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 free       N      73196          4

         4        151 xcur       N      73196          4

session2

對數據塊進行更新操作,但不提交

update scott.emp set sal = 1000 where empno =7369;

session1

查詢緩存塊,dirty列標志為Y,表示為臟數據

select file#, block#, status, dirty, objd, ts# from v$bh where file#=4 and block#=151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 free       N      73196          4

         4        151 xcur       Y      73196          4

再次對數據做查詢操作

select * from scott.emp;

查詢緩存塊,又多了一個cr版本,因為之前session2的更新沒有提交,所以session1查詢時,通過讀取回滾段在buffer cache中構建了CR塊。

select file#, block#, status, dirty, objd, ts# from v$bh where file#=4 and block#=151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 free       N      73196          4

         4        151 xcur       Y      73196          4

         4        151 cr         N      73196          4

session2

提交更新

commit;

session1

再次對數據做查詢操作

select * from scott.emp;

查詢緩存塊,狀態信息不變,因為是否提交并不影響數據塊內容

select file#, block#, status, dirty, objd, ts# from v$bh where file#=4 and block#=151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 free       N      73196          4

         4        151 xcur       Y      73196          4

         4        151 cr         N      73196          4

session2

再次更新數據,但不提交

update scott.emp set sal = 800 where empno =7369;

session1

對數據做查詢操作

select * from scott.emp;

查詢緩存塊,可以看到又新構建了一個CR版本

select file#, block#, status, dirty, objd, ts# from v$bh where file#=4 and block#=151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 free       N      73196          4

         4        151 xcur       Y      73196          4

         4        151 cr         N      73196          4

         4        151 cr         N      73196          4

session2

提交更新

commit;

session1

對數據做查詢操作

select * from scott.emp;

查詢緩存塊,狀態不改變

select file#, block#, status, dirty, objd, ts# from v$bh where file#=4 and block#=151;

     FILE#     BLOCK# STATUS     D       OBJD        TS#

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

         4        151 free       N      73196          4

         4        151 xcur       Y      73196          4

         4        151 cr         N      73196          4

         4        151 cr         N      73196          4

數據塊在緩存中的狀態及其物理意義如下:

freenot currently in use

xcurexclusive

scurshared current

crconsistent read

readbegin read from disk

mrecin media recovery mode

irecin instance recovery mode

關于如何進行ITL與事務處理問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

itl
AI

博白县| 团风县| 丰镇市| 肥西县| 沁源县| 宜宾市| 滨海县| 大宁县| 孟津县| 金昌市| 景洪市| 尚义县| 铜陵市| 柘城县| 彭阳县| 武川县| 宜春市| 郯城县| 资源县| 龙里县| 大关县| 牟定县| 阳信县| 广昌县| 明水县| 洪洞县| 剑川县| 德安县| 兴化市| 临西县| 阿合奇县| 鲁甸县| 海安县| 弋阳县| 本溪| 偃师市| 紫阳县| 龙游县| 玉溪市| 海门市| 湖南省|