您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“怎么理解Oracle事務(wù)”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“怎么理解Oracle事務(wù)”吧!
oracle事務(wù)
1概述
事務(wù)由一個或多個DML語句組成,起始于第一條DML語句,終止于DDL或者DCL語句??梢栽谑聞?wù)內(nèi)使用SAVEPOINT命令給出控制程度。,通過事務(wù)機制確保這一組SQL語句所作的操作要么完全成功執(zhí)行,完成整個工作單元操作,要么一點也不執(zhí)行。
2事務(wù)的特性
3事務(wù)控制
1 COMMIT命令
許多人(甚至某些經(jīng)驗豐富的DBA)在提交處理這個環(huán)節(jié)上都會出現(xiàn)不完全或者完全錯誤的理解oracle體系結(jié)構(gòu)的情況。執(zhí)行COMMIT命令時發(fā)生的所有物理操作時LGWR進(jìn)程將日志緩沖區(qū)的內(nèi)容刷新到磁盤。DBWn進(jìn)程完全沒有執(zhí)行任何操作。對于oracle數(shù)據(jù)庫來說,這是一個非常重要的性能特性。
注意:執(zhí)行COMMIT命令時,DBWn進(jìn)程不會進(jìn)行任何操作。
為了使某個事務(wù)持久,所需的全部工作是將組成這個事務(wù)的變更寫入磁盤(不必使實際表數(shù)據(jù)存在于磁盤的數(shù)據(jù)文件上)。如果變更以多重重做日志文件的形式存在于磁盤上,那么在出現(xiàn)使數(shù)據(jù)庫受損的事件時,通過從數(shù)據(jù)庫受損前所做的備份中還原數(shù)據(jù)文件以及應(yīng)用重做日志文件中的變更,就可以重新實例化事務(wù)。
2 ROLLBACK命令
在事務(wù)處理過程中,Oracle會保存事務(wù)處理之前數(shù)據(jù)的映像。在事務(wù)處理過程中,會將這個映像提供給查詢數(shù)據(jù)的其他會話。如果出現(xiàn)錯誤,或者會話故意請求回滾,那么它也可以用來自動回滾事務(wù)。
回滾之前數(shù)據(jù)的狀態(tài)是,數(shù)據(jù)已經(jīng)改變,但反轉(zhuǎn)這些變更所需的信息是可用的。為了滿足隔離性原則,會將這些信息提供給其他所有會話。回滾會恢復(fù)數(shù)據(jù)改變之前的映像,從而拋棄所有變更;事務(wù)插入的所有行都會刪除,(這里留個疑問)事務(wù)刪除的所有行都會重新插入表中,已經(jīng)更新的行會回到原始狀態(tài)。其他會話根本不知道發(fā)生了什么,它們絕對看不到這些變更。處理事務(wù)的會話現(xiàn)在會將數(shù)據(jù)看做事務(wù)開始之前的數(shù)據(jù)。
3 SAVEPOINT命令
使用保存點就是允許編程人員在事務(wù)中設(shè)置一個標(biāo)記,這個標(biāo)記可以用來控制ROLLBACK命令的效果。除了回滾整個事務(wù)并終止它之外,還可以反轉(zhuǎn)在特定點之后所做的所有變更,同時保持在該點之前所做的變更不變。事務(wù)本身繼續(xù)進(jìn)行:仍然沒有提交,仍然可以回滾,仍然對其他會話不可見。
3.1使用savepoint的規(guī)則:
(1)所有的savepoint語句都必須包含一個名稱。在后臺,您所創(chuàng)建的savepoint名稱會與"系統(tǒng)變更號"(system change number,scn)"相關(guān)聯(lián)。這是savepoint所標(biāo)注的對象。
(2)在一個事務(wù)中不應(yīng)當(dāng)重復(fù)savepoint的名稱,事務(wù)是以提交事件作為結(jié)束的一連串的SQL語句。如果重復(fù)一個名稱,那么不會看到語法錯誤或執(zhí)行錯誤。相反,新的savepoint會覆蓋較早的savepoint,從效果上是將之前的存儲點刪除了。
(3)一旦提交事件發(fā)生,無論是顯示或隱式提交事件,則所有現(xiàn)有的存儲點都將會從內(nèi)存中被刪除。
4 SELECT FOR UPDATE
最后一個事務(wù)控制語句是SELECT FOR UPDATE。在默認(rèn)情況下,Oracle提供最高級別的并發(fā)性:讀者不打斷寫者,寫者也不打斷讀者?;蛘吆唵蔚恼f,一個會話查詢另一個會話正在更新的數(shù)據(jù),或者一個會話更新另一個會話正在查詢的數(shù)據(jù),這都沒有問題。然而,有時需要改變這種行為,防止改變正在被查詢的數(shù)據(jù)。
應(yīng)用程序使用SELECT命令檢索一組行,將它們提供給用戶精讀,并給用戶提示所做的變更,這種情況不是不常見。因為ORACLE是一個多用戶數(shù)據(jù)庫,所以另一個會話也要檢索這些行也不是不可能。如果這兩個會話都要做出變更,那么會出現(xiàn)一些奇怪的效果。
Session1 | Session2 | |
select * from emp; 出現(xiàn)N條數(shù)據(jù),其中包括id=1的數(shù)據(jù) | ||
用戶刪除emp表一條數(shù)據(jù) delete from emp where id=1; | ||
update emp set name='test' where id=1; 此時會出現(xiàn)"0 rows updated" | ||
解決這個問題的方法之一就是鎖定用戶感興趣的行: select * from emp for update; |
FOR UPDATE子句會鎖定所有檢索的行。除了發(fā)出命令的會話之外,其他任何會話都不能改變它們,因此后面的更新操作就會成功。這意味著一個會話有一致的數(shù)據(jù)視圖(不會改變),但付出的代價是如果其他會話要更新鎖定的行,它們就會掛起(當(dāng)天他們可以查詢)。
在發(fā)出命令的會話發(fā)出COMMIT或ROLLBACK命令之前,會一直保持FOR UPDATE子句設(shè)置的鎖定。必須這樣來釋放鎖定,即使沒有執(zhí)行DML命令。
5 所謂的"自動提交"
在結(jié)束對提交處理的討論之前,我們有必要闡明一下經(jīng)常被提及的"自動提交"(有時候也被稱為隱式提交)。您經(jīng)常會聽到這樣的說法:Oracle在某些情況下可以進(jìn)行"自動提交"。
執(zhí)行DDL語句就是其中一種情況,
退出某個用戶進(jìn)程(SQL*Plus)則是另一種情況。
"自動提交"純屬子虛烏有。執(zhí)行某條DDL語句時,實現(xiàn)這個DDL命令的源代碼包含了一個完全正規(guī)的COMMIT命令。但是,退出用戶進(jìn)程時的情況是怎樣呢?
執(zhí)行"退出"命令(正常) | 直接點擊右上角關(guān)閉(異常) | |
Windows | 提交 | 回滾 |
Linux | 提交 | 回滾 |
如果在WINDOWS終端上使用SQL*Plus并執(zhí)行一條DML語句,然后再執(zhí)行"退出"命令,就會提交事務(wù)。這是因為SQL*Plus中的"退出"命令嵌入了一條COMMIT語句。
但是,單擊SQL*Plus窗口的右上角此時,關(guān)閉SQL*Plus窗口,如果再次登錄SQL*Plus,您會發(fā)現(xiàn)已回滾了事務(wù)。這是因為為Microsoft Windows編寫SQL*Plus的編程人員在關(guān)閉SQL*Plus窗口的代碼中嵌入了一條ROLLBACK語句。
SQL*Plusz在其他平臺上的行為可能有所不同,唯一的確認(rèn)方法是測試。因此,以不同方式退出某個程序時是否能夠進(jìn)行"自動提交"完全取決于編程人員如果編寫用戶進(jìn)程。Oracle服務(wù)器只是按照指令進(jìn)行操作。
4 oracle提交數(shù)據(jù)的類型
1 顯式提交
用COMMIT命令直接完成的提交為顯式提交。
其格式為:SQL>COMMIT;
2 隱式提交
用SQL命令間接完成的提交為隱式提交
這些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。 執(zhí)行這些命令前oracle會執(zhí)行一次commit,命令執(zhí)行完后oracle也會自動執(zhí)行一次commit
3 自動提交
若把AUTOCOMMIT設(shè)置為ON,則在插入、修改、刪除語句執(zhí)行后,系統(tǒng)將自動進(jìn)行提交,這就是自動提交。 其格式為:SQL>SET AUTOCOMMIT ON; 它只是DML語句執(zhí)行后的自動提交,對會話的正常退出或異常退出都沒有作用。
這個參數(shù)屬于客戶端sqlplus,oracle自身并沒有這個參數(shù)
查看這個參數(shù)的值:
SHOW AUTOCOMMIT
設(shè)置這個參數(shù)的值:
SET AUTO[COMMIT] { OFF | ON | IMM[EDIATE] | n }
5 ITL(事務(wù)槽)
1 ITL描述
ITL(Interested Transaction List)是Oracle數(shù)據(jù)塊內(nèi)部的一個組成部分,位于數(shù)據(jù)塊頭(block header),
每一個oracle塊的頭部都有事務(wù)槽,oracle塊里有一個PCT_free的概念,即oracle會預(yù)留塊大小的10%作為緩沖,當(dāng)修改oracle的事務(wù)增加時,事務(wù)槽向下增長,當(dāng)更新oracle塊的數(shù)據(jù)時,數(shù)據(jù)向上增長,PCT_free的空間被壓縮。當(dāng)PCT_free被用完時,oracle就徹底填滿了,如果還有事務(wù)要修改Oracle塊,就需要在事務(wù)隊列中等待這叫做事務(wù)槽的爭用。
itl由xid,uba,flag,lck和scn/fsc組成,用來記錄該塊所有發(fā)生的事務(wù),一個itl可以看作是一條事務(wù)記錄。當(dāng)然,如果這個事務(wù)已經(jīng)提交,那么這個itl的位置就可以被反復(fù)使用了,因為itl類似記錄,所以,有的時候也叫itl槽位。如果一個事務(wù)一直沒有提交,那么,這個事務(wù)將一直占用一個itl槽位,itl里面記錄了事務(wù)信息,回滾段的入口,事務(wù)類型等等。如果這個事務(wù)已經(jīng)提交,那么,itl槽位中還保存的有這個事務(wù)提交時候的SCN號。
dump一個數(shù)據(jù)塊可以在事務(wù)區(qū)看到ITL信息
Block header dump: 0x01001543 Object id on Block? Y seg/obj: 0x15c5a csc: 0x00.1ce6af itc: 3 flg: E typ: 1 - DATA brn: 0 bdba: 0x1001540 ver: 0x01 opc: 0 inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc 0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.001ce6af 0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 bdba: 0x01001543 |
Object id on Block? Y是表示是否是對象的塊
0x01001543是數(shù)據(jù)文件號塊號
seg/obj: 0x15c5a是對象id 89178,它是rowid的前6個64進(jìn)制字符AAAVxa的16進(jìn)制形式,在dump(rowid,16)中的前4位中也可以看出,可參考:http://blog.itpub.net/28539951/viewspace-1986647/
csc: 0x00.1ce6af是The cleanout SCN that is used during read consistency
itc: 3是塊中itl slot的數(shù)量 flg: E E是使用ASSM O是使用free list
typ: 1 - DATA 1是數(shù)據(jù),2是索引
brn: 0
bdba: 0x1001540是Block relative data block address
ver: 0x01
opc: 0 inc: 0 exflg: 0
Itl是塊上相關(guān)事務(wù)列表interested transaction list 每條記錄中的行級鎖對應(yīng)于Itl列表中的序號,即哪個事務(wù)在該記錄上產(chǎn)生的鎖
Xid是事務(wù)id.Xid=Undo Segment Number XIDUSN+Transaction Table Slot Number XIDSLOT+ Wrap XID = usn#.slot#.warp#
Uba是該事務(wù)對應(yīng)的回滾段地址.Uba=回滾塊地址(undo文件號UBAFIL和數(shù)據(jù)塊號UBABLK)+回滾序列號UBASQN+回滾記錄號UBAREC
Flag是事務(wù)標(biāo)志位 ---= 事務(wù)是活動的,或者在塊清除前提交事務(wù) C =事務(wù)已經(jīng)提交并且清除了行鎖定 B = this undo record contains the undo for this ITL entry U =事務(wù)已經(jīng)提交(SCN已經(jīng)是最大值),但是鎖定還沒有清除(快速清除) T = transaction was still active at block cleanout SCN
Lck是這個事務(wù)影響的行數(shù)
Scn/Fsc是scn或者free space credit |
相關(guān)實驗可以參考
https://blog.csdn.net/gumengkai/article/details/63684545
2事務(wù)槽參數(shù)
每個塊都有一個塊首部。這個塊首部中有一個事務(wù)表。事務(wù)表中會建立一些條目來描述哪些事務(wù)將塊上的哪些行/元素鎖定。這個事務(wù)表的初始大小由對象的INITRANS 設(shè)置指定。對于表,這個值默認(rèn)為2(索引的INITRANS 也默認(rèn)為2)。事務(wù)表會根據(jù)需要動態(tài)擴(kuò)展,最大達(dá)到MAXTRANS 個條目(假設(shè)塊上有足夠的自由空間)。所分配的每個事務(wù)條目需要占用塊首部中的23~24 字節(jié)的存儲空間。注意,對于Oracle 10g,MAXTRANS 則會忽略,所有段的MAXTRANS 都是255。
設(shè)initrans值為2,則數(shù)據(jù)庫服務(wù)器在一個數(shù)據(jù)塊中最多有兩個并行的事務(wù)可以獨立、并行的通過自己的事務(wù)槽,實現(xiàn)對共享數(shù)據(jù)塊中的行數(shù)據(jù)的事務(wù)操作。
也就是說,如果某個事物鎖定了這個塊的數(shù)據(jù),則會在這個地方記錄事務(wù)的標(biāo)識,當(dāng)然那個事務(wù)要先看一下這個地方是不是已經(jīng)有人占用了,如果有,則去看看那個事務(wù)是否為活動狀態(tài)。如果不活動,比如已經(jīng)提交或者回滾,則可以覆蓋這個地方。如果活動,則需要等待(閂的作用)。所以,如果有大量的并發(fā)訪問使用的這個塊,則參數(shù)不能太小,否則資源競爭將導(dǎo)致系統(tǒng)并發(fā)性能下降。
ORACLE 并發(fā)insert事務(wù)的時候的塊分配和ITL管理
INITRANS =1 時 并發(fā)多個INSERT 事務(wù)(本次測試最多5個)的時候并不會由于ITL的爭用而等待組塞,ORACLE 采取的策略是每個INSERT事物分配不同的一些塊來使用,這樣各個會話之間就不會產(chǎn)生沖突,除非段沒有多余的塊。
創(chuàng)建一張表,并查看建表的參數(shù) create table t1(id int,num int); select TABLE_NAME,STATUS,PCT_FREE,PCT_USED,INI_TRANS,MAX_TRANS,INITIAL_EXTENT,NEXT_EXTENT,MIN_EXTENTS,MAX_EXTENTS,PCT_INCREASE from user_tables where table_name='T1'; |
插入數(shù)據(jù) insert into t1 values(1,1); insert into t1 values(2,1); insert into t1 values(3,1); insert into t1 values(4,1); commit; |
查看表的數(shù)據(jù)的分布 select ID,num ,dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from T1; |
會話1 插入數(shù)據(jù)查看,發(fā)現(xiàn)插入到4號文件的532號塊 insert into t1 values(5,1); select ID,num ,dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from T1; |
會話2 插入數(shù)據(jù)查看,發(fā)現(xiàn)插入到4號文件的533號塊 insert into t1 values(6,1); select ID,num ,dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from T1; |
會話2 插入數(shù)據(jù)查看,發(fā)現(xiàn)插入到4號文件的535號塊 insert into t1 values(9,9); select ID,num ,dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block# from T1; 綜上所述INSERT事物分配不同的一些塊來使用,這樣各個會話之間就不會產(chǎn)生沖突,除非段沒有多余的塊 |
ORACLE 并發(fā)update事務(wù)的時候的塊分配和ITL管理
INITRANS =1 時 并發(fā)多個UPDATE事務(wù)(本次測試最多7個)的時候也不會由于ITL的爭用而導(dǎo)致等待產(chǎn)生,此時ORACLE除了使用默認(rèn)的ITL之外,另外動態(tài)擴(kuò)展所需要的ITL,緊緊在非常極端的情況下才會出現(xiàn)等待。
1) 該BLOCK沒有FREE空間了,注意FREE參數(shù)的設(shè)置不能太小。
2) 該塊使用的ITL總數(shù),超過該塊允許的ITL的最大值min(round(block_size*0.5/24) - 2 ,255) 。
要達(dá)到這樣的極端情況實際的生產(chǎn)情況是很難的,應(yīng)該比業(yè)務(wù)SQL的死鎖出現(xiàn)的概率更小。
3 ITL等待
發(fā)生等待的場景:
1.超過maxtrans配置的最大ITL數(shù)
2.initrans不足,沒有足夠的free space來擴(kuò)展ITL
解決方法:
maxtrans不足:
這一情況是由高并發(fā)引起的:同一數(shù)據(jù)塊上的事務(wù)量已經(jīng)超出了其實際允許的ITL數(shù)。因此,要解決這類問題就需要從應(yīng)用著手,減少事務(wù)的并發(fā)量;長事務(wù),在保證數(shù)據(jù)完整性的前提下,增加commit的頻率,修改為短事務(wù),減少資源占用事件。而對于OLAP系統(tǒng)來說(例如,其存在高并發(fā)量的數(shù)據(jù)錄入模塊),可以考慮增大數(shù)據(jù)塊大小。
initrans不足:
數(shù)據(jù)塊上的ITL數(shù)量并沒有達(dá)到MAX TRANS的限制,發(fā)生這種情況的表通常會被經(jīng)常UPDATE,從而造成預(yù)留空間(PCTFREE)被填滿。如果我們發(fā)現(xiàn)這類ITL等待對系統(tǒng)已經(jīng)造成影響,可以通過增加表的INITRANS或者PCTFREE來解決(視該表上的并發(fā)事務(wù)量而定,通常,如果并發(fā)量高,建議優(yōu)先增加INITRANS,反之,則優(yōu)先考慮增加PCTFREE)。
要注意的一點是,如果是使用ALTER TABLE的方式修改這2個參數(shù)的話,只會影響新的數(shù)據(jù)塊,而不會改變已有數(shù)據(jù)的數(shù)據(jù)塊——要做的這一點,需要將數(shù)據(jù)導(dǎo)出/導(dǎo)入、重建表。
Oracle事務(wù)相關(guān)概念
1 事務(wù)id
每一個事物都有一個自己的事物ID,就像身份證號一樣。
在v$transaction數(shù)據(jù)字典中xid就是事物ID,xid既是一個編號,也是一個地址,xid中內(nèi)容的有
1、使用哪個回滾段的段頭塊;XIDUSN
2、一個undo段最多同時能有47個活動事物,一個undo段只有一個事物表,47個事物的情況都在事物表中 ,一個事物占用一行,此次事物使用47中的哪一行;XIDSLOT
3、該行被覆蓋的次數(shù)。XIDSQN
select xid,xidusn,xidslot,xidsqn,start_time,start_scnb,used_ublk,used_urec,log_io,phy_io from v$transaction;
注:過一段時間在查詢,若used_urec 字段不斷增加,說明該事物正在繼續(xù),如果該字段不斷下降,說明該事物正在回滾
聯(lián)合v$session 再查一次,這樣就知道是哪個用戶的哪些事務(wù)了并且獲取sid
select b.sid,b.username,xid,a.status,start_time,used_ublk,used_urec,log_io,phy_io from v$transaction a,v$session b where a.ses_addr = b.saddr;
獲得sid這樣就知道是哪個用戶的哪些事務(wù)了,進(jìn)而可以跟蹤到sql
select sql_text from v$sqlarea a,v$session b where a.SQL_ID=b.PREV_SQL_ID and b.SID=&sid;
V$TRANSACTION各列字段的含意
列名 數(shù)據(jù)類型 含義 ADDR RAW(4|8) Address of the transaction state object XIDUSN NUMBER 使用的回滾段號,可以和v$rollstat對應(yīng) XIDSLOT NUMBER RBS TX 表中的槽號 USN.SLOT.SQN XIDSQN NUMBER 序列號,slot被重復(fù)使用的次數(shù)TX-USNxSLOT-SQNxxxxx UBAFIL NUMBER 最后一個撤銷塊地址所在的文件號 UBABLK NUMBER UBA 塊號 UBASQN NUMBER UBA 序列號 UBAREC NUMBER UBA 記錄號 STATUS VARCHAR2(16) 當(dāng)前事務(wù)的狀態(tài) START_TIME VARCHAR2(20) Start time (wall clock) START_SCNB NUMBER 開始的系統(tǒng)改變號 START_SCNW NUMBER Start SCN wrap START_UEXT NUMBER Start extent number START_UBAFIL NUMBER Start UBA file number START_UBABLK NUMBER Start UBA block number START_UBASQN NUMBER Start UBA sequence number START_UBAREC NUMBER Start UBA record number SES_ADDR RAW(4|8) 用戶會話對象地址,對v$session 的saddr列 FLAG NUMBER Flag SPACE VARCHAR2(3) YES if a space transaction RECURSIVE VARCHAR2(3) YES if a recursive transaction NOUNDO VARCHAR2(3) YES if a no undo transaction PTX VARCHAR 2(3) YES if parallel transaction NAME VARCHAR2(256) Name of a named transaction PRV_XIDUSN NUMBER Previous transaction undo segment number PRV_XIDSLT NUMBER Previous transaction slot number PRV_XIDSQN NUMBER Previous transaction sequence number PTX_XIDUSN NUMBER Rollback segment number of the parent XID PTX_XIDSLT NUMBER Slot number of the parent XID PTX_XIDSQN NUMBER Sequence number of the parent XID DSCN-B NUMBER This column is obsolete and maintained for backward compatibility. The value of this column is always equal to the value in DSCN_BASE. DSCN-W NUMBER This column is obsolete and maintained for backward compatibility. The value of this column is always equal to the value in DSCN_WRAP. USED_UBLK NUMBER 已占用的undo 塊數(shù) USED_UREC NUMBER 已使用的undo 記錄數(shù) LOG_IO NUMBER 邏輯 I/O PHY_IO NUMBER 物理 I/O CR_GET NUMBER 一致讀的次數(shù) CR_CHANGE NUMBER Consistent changes START_DATE DATE Start time (wall clock) DSCN_BASE NUMBER Dependent SCN base DSCN_WRAP NUMBER Dependent SCN wrap START_SCN NUMBER Start SCN DEPENDENT_SCN NUMBER Dependent SCN XID RAW(8) Transaction XID PRV_XID RAW(8) Previous transaction XID PTX_XID RAW(8) Parent transaction XID |
通過xid獲取usn/slot/sqn方式如下:
with v as(select '0200010068050000' xid from dual) select to_number(substr(v.xid,3,2)||substr(v.xid,1,2),'xxxx') usn, to_number(substr(v.xid,7,2)||substr(v.xid,5,2),'xxxx') slot, to_number(substr(v.xid,15,6)||substr(v.xid,13,2)||substr(v.xid,11,2)||substr(v.xid,9,2),'xxxxxxxxxx') sqn from v; |
2 事務(wù)表
undo表空間的undo段的第一個數(shù)據(jù)塊(即undo段的段頭塊)里放事物表,共有47行。事物開始第一件事就是在事物表中找到一個空行,寫上事物信息。也就是說undo段最多47個活動事物,但是oracle會盡量將一個事物放到一個段上,為了均勻分配(undo段的段頭塊的位置在dba_segments表空間可以查得)。
事務(wù)管理起始于undo段,并以此為中心。undo段的第一個塊(段頭塊)包含如下結(jié)構(gòu):擴(kuò)展映射,擴(kuò)展控制頭(跟其他類型的段頭塊一樣),事務(wù)表,事務(wù)控制區(qū)(特殊的結(jié)構(gòu))。事務(wù)表的大概結(jié)構(gòu)如下:
dump一個undo段的一個塊可以看到事務(wù)表
index 表示事務(wù)表中槽號,只是一個序列而已,從0x00開始到0x21結(jié)束,11g的版本有34個槽。
state 表示事務(wù)狀態(tài):9代表事務(wù)不活動,10代表事務(wù)正在活動,從這里我們看出16進(jìn)制第0x17號槽上的事務(wù)正在活動。大家有沒有發(fā)現(xiàn),我們在發(fā)生事務(wù)前,Oracle會找事務(wù)控制列表中的chd=0x0017,說白了就是重從index=0x17的槽,存放當(dāng)前最新的事務(wù):
注:下面的事務(wù)控制,是我在發(fā)生事務(wù)前(即做update gyj_test set name='GGGGG' where id=1;前所DUMP的事務(wù)控制)
TRN CTL:: seq: 0x000d chd: 0x0017 ctl: 0x000b inc: 0x00000000 nfb:0x0001
mgc: 0xb000 xts: 0x0068 flg: 0x0001 opt: 2147483646 (0x7ffffffe)
uba: 0x0280000a.000d.2b scn: 0x0000.0028a26a
cflags 表示正在使用穿上事務(wù)槽的事務(wù)的狀態(tài):0x00表示非活動事務(wù)、0x80表示活動事務(wù)、0x10表示死事務(wù)、0x90表示被回滾的死事務(wù)
平時我們看到的最多就是0x00表示非活動事務(wù)、0x80表示活動事務(wù),后面的很少發(fā)生。
wrap# 表示事務(wù)表上的事務(wù)槽被重用的次數(shù),它是XID的一部分。0x001d表示此時事務(wù)槽被重用了29次。
uel 表示當(dāng)前活動事務(wù)所在事務(wù)槽的下一個事務(wù)槽的指針(即如果又發(fā)生一個新的事務(wù),此時就會用到UEL指向的事務(wù)槽上的index)。
scn 表示務(wù)事啟動、提交、回滾的SCN.
dba 表示uba:第一部分的undo塊地址,這個DBA是(rollback)回滾的起始點,也就是說是記錄事務(wù)修改的最后一條記錄所在UNDO塊的地址。
nub 表示當(dāng)前事務(wù)所用到的UNDO塊的個數(shù)。
cmt 表示最接近當(dāng)前的提交時間戳,是從1970年1月1號零晨開始的(以秒為單位記錄)。0表示事務(wù)正在活動。 |
oracle中有哪些undo段:
select * from v$rollname; |
3 事物槽
在每個數(shù)據(jù)塊的塊頭部分有事物槽,事物槽包括xid、uba(undo block address)等等
當(dāng)事物發(fā)生的時候,
第一件事會在undo表空間的相對空閑的undo段的段頭塊的事物表中找到一個槽位,寫上事物信息(xid),給這個事物分配一個undo塊(undo塊里寫的就是修改之前的數(shù)據(jù)),然后將undo塊的地址(即uba寫到事物表中),所以現(xiàn)在事物表中有xid和uba;
第二件事在要修改的數(shù)據(jù)塊的塊頭的事物槽中找到槽位,寫上事物信息(xid),(目的是通過數(shù)據(jù)塊上的xid可以找到事物表),然后在將要修改的數(shù)據(jù)塊上修改數(shù)據(jù),修改之前的信息寫到undo塊里。同時,在事物槽中也寫上uba地址,指向回滾塊。為什么要在兩個地方寫事物信息呢?下面有解釋。
當(dāng)回滾塊的數(shù)據(jù)寫滿之后,系統(tǒng)會自動分配一個回滾塊,比如該事物修改了較多的數(shù)據(jù),產(chǎn)生3個undo塊,3個undo塊有先后關(guān)系,它們會鏈起來,但是這是事物表中的uba就只是指向最新的undo塊,這是便于回滾。
數(shù)據(jù)塊的事物槽中的uba指向回滾數(shù)據(jù),這便于構(gòu)造CR塊。
一個事物一個事物槽,只有當(dāng)事物提交了,該事物槽才能被覆蓋。
pctfree:1、當(dāng)執(zhí)行更新操作時,也許會占用pctfree的空間。2、當(dāng)多個事物操作該數(shù)據(jù)塊時,需要增加事物槽的數(shù)量,也會占用pctfree,但是如果事物過多,pctfree不夠用了,(之前的事物槽未提交,就不能覆蓋,該數(shù)據(jù)塊又有新的事物產(chǎn)生,需要新的事物槽)這樣就會產(chǎn)生事物槽爭用的情況,大多數(shù)發(fā)生在update和delete的情況,insert不會發(fā)生。因為oracle會盡量的將insert插入的數(shù)據(jù)插入到多個塊中,也就是平均一下,但是update和delete就無能為力了,因為這兩個操作往往是針對某一行進(jìn)行的,而某一行特定就是在這個塊里。
到此,相信大家對“怎么理解Oracle事務(wù)”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。