1、事務:
<a href="http://blog.csdn.net/changyanmanman/article/details/7019957"></a>
語句級復原和可恢複空間的配置設定問題:
語句級的復原一般發生在一條sql語句執行出現錯誤的時候,這一條語句的復原不會影響整個事務,在此語句之前的ddl語句隐式送出的工作都是有效的;
當處于可恢複空間配置設定模式的事務需要配置設定空間,但是由于空間不足或者達到最大資料擴充的限制時,oracle資料庫不會直接報錯,它會将此事務挂起,相關占用的空間保留,等到别的事務送出,釋放空間,此事務需要的空間足夠了,就會再次執行。。(我覺得這樣形成類似死鎖的資源争用很容易,正好兩個事務都挂起了,都等着對方釋放資源怎麼辦?)
在一個修改了資料的事務送出之前,oracle會做以下工作:
1、在撤銷表空間内生成撤銷資訊,這些資訊包括sql語句所修改資訊的原始值(以備撤銷時使用),
2、oracle在SGA的重做日志緩沖區(redo log buffer)中生成重做日志條目(redo log entry)這些條目的重做日志記錄(redo log record)中包含了對資料塊和復原塊所進行的修改操作,這些記錄可能在送出事務之前就被寫入磁盤。
已經送出的事務對資料的修改存儲在SGA的資料庫緩沖區(buffer cache)中,他們不一定立即被背景寫入程序(DBWn)寫入資料檔案中,oracle會自己選擇合适的機會寫入,以保證資料庫的效率。
在一個事務被送出後,oracle做一下工作:
1、撤銷表空間(undo tablespace)内部的對應撤銷段内的事務表(transaction table)将記錄此次送出,oracle将為此事務配置設定一個唯一的系統變化編号(system change number 即SCN)并将其記錄在事務表中。
2、重做日志寫程序(LGWR)将SGA中的重做日志緩沖區中的重做日志條目寫入重做日志檔案,同時也将此事務的SCN好寫入線上重做日志檔案
這兩個操作構成原子事件,标志着一個事務的完整送出。
3、oracle釋放加在表和資料行上的鎖。
4、oracle 将事務标記為完成。
在預設狀态下,LGWR 将重做資訊(redo log)寫入聯機重做日志檔案(online redo log file)的工作應與事務(transaction commit)送出同步,重做資訊寫入磁盤後系統才能通知使用者送出(commit)結束。但是為了縮短事務送出帶來的延遲,應用開發者可以設定事務送出 與重做資訊寫入異步地執行,即事務送出無需等待重做資訊被寫入磁盤就可以結束。
2、ITL 事物槽
什麼是Interested Transaction List(ITL) ?
ITL是block中的相關事務資訊的記錄(在塊首部的一個區域内,用來記錄該塊發生的所有事務),一個itl可以看做是一個記錄,它記錄了在某一個時間這個塊上的事務(包括已經送出和
未送出的事務) 。當然,如果這個事務已經送出,那此事務對應的itl槽位就可以被覆寫重用。
ITL 是 consistents
reads(一緻性讀) 的基礎,根據ITL (内部有uba)才能去復原段中找變化前的資料 。 如果這個事務已經送出,那麼這個ITL的位置就可以被反複使用了,因為ITL類似記錄,是以,有的時候也叫itl槽位。
如果一個事務沒有送出,那麼此事務對應的itl将一直占用這個itl槽位,itl裡面記錄了此
事務的資訊(包括此事務ID(xid),list編号(這個list是一個與事務相關的送出清單,每個表有20個資料塊)、事務類型、事務狀态[送出否]、事務在該block影響的記錄條數等)
復原段位址(uba)(這個位址指向復原段中的某一個塊,可以根據這個塊中復原段的位址找到資料變化前的塊的那個映像資料,不一定是一個整塊哦)。
塊上鎖的狀态(lck) SCN等。
dump一個塊可以看到ITL資訊類似如下:
Itl Xid Uba
Flag Lck Scn/Fsc
0x01 0x0006.002.0000158e 0x0080104d.00a1.6e --U- 734 fsc 0x0000.6c9deff0
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
Xid:事務id,在復原段事務表(關于這個復原段事務表,我們将會在以後專門有介紹)中有一條記錄和這個事務對應
Uba:復原段位址,該事務對應的復原段位址
第一段位址:復原資料塊的位址,包括復原段檔案号和資料塊号
第二段位址:復原序列号
第三段位址:復原記錄号
SELECT UBAFIL 復原段檔案号,UBABLK 資料塊号,UBASQN 復原序列号,UBAREC 復原記錄号 FROM v$transaction —— 檢視UBA
Flag:事務标志位。這個标志位就記錄了這個事務的操作,各個标志的含義分别是:
- - - - =》 事務是活動的,或者在塊清除前送出事務(還沒有執行塊清除)。
C--- =》 事務已經送出并且清除了行鎖定。
-B-- = 》this undo record contains the undo for this ITL entry
--U- =》 事務已經送出(SCN已經是最大值),但是鎖定還沒有清除(快速清除)。
---T =》當塊清除的SCN被記錄時,該事務仍然是活動的,塊上如果有已經送出的事務,那麼在clean ount的時候,塊會被進行清除,但是這個塊裡面的事務不會被清除。
Lck:影響的記錄數
Scn/Fsc:快速送出(Fast Commit Fsc)的SCN或者Commit SCN。
每條記錄中的行級鎖對應于Itl清單中的序号,即哪個事務在該記錄上産生的鎖。
什麼是ITL等待?
ITL個數其最小值為1,由參數initrans控制(由于相容性的原因,oracle會在對象的存儲塊配置設定兩個itl,是以initrans的最小值實際上為2),最大值為255,由參數maxtrans控制,最大值參數在10g以後不能被修改,itl是block級的概念,一個itl占用塊46B的空間,參數initrans意味着塊中除去block
header外一部分存儲空間無法被記錄使用(46B*initrans),當塊中還有一定的free space時,oracle可以使用free space建構itl供事務使用,如果沒有了free space,那麼,這個塊因為不能配置設定新的itl,是以就可能發生itl等待。
發生等待的場景:
1.超過maxtrans配置的最大ITL數
2.initrans不足,沒有足夠的free space來擴充ITL
如何診斷ITL等待?怎樣調整INITRANS 的值 ?
解決方法:
1.maxtrans不足:這一情況是由高并發引起的:同一資料塊上的事務量已經超出了其實際允許的ITL數。是以,要解決這類問題就需要從應用着手,減少事務的并發量;長事務,在保證資料完整性的前提下,增加commit的頻率,修改為短事務,減少資源占用事件。而對于OLAP系統來說(例如,其存在高并發量的資料錄入子產品),可以考慮增大資料塊大小。
2.initrans不足:資料塊上的ITL數量并沒有達到MAX TRANS的限制,發生這種情況的表通常會被經常UPDATE,進而造成預留白間(PCTFREE)被填滿。如果我們發現這類ITL等待對系統已經造成影響,可以通過增加表的INITRANS或者PCTFREE來解決(視該表上的并發事務量而定,通常,如果并發量高,建議優先增加INITRANS,反之,則優先考慮增加PCTFREE)。
要注意的一點是,如果是使用ALTER TABLE的方式修改這2個參數的話,隻會影響新的資料塊,而不會改變已有資料的資料塊——要做的這一點,需要将資料導出/導入、重建表。
如果在并發量特别大的系統中,最好配置設定足夠的itl個數,其實它并浪費不了太多的空間,或者,設定足夠的pctfree,保證itl能擴充,但是pctfree有可能是被行資料給消耗掉的,如update,是以,也有可能導緻塊内部的空間不夠而導緻itl等待。
每一個ITL 對應一個 SCN 。如果這個事務已經送出,那麼,ITL槽位中還儲存的有這個事務送出時候的SCN号(但是這個SCN号也已經寫入了redo日志裡了,不然一會就覆寫了)。
對于已經送出的事務,itl槽位最好不要馬上被覆寫,因為一緻性讀可能會用到這個資訊,一緻性讀的時候,可能需要從這裡獲得復原段的入口,并從復原段中獲得一緻性讀。
如何減少ITL等待?
如果想增加initrans個數,參數可以動态修改,但是,隻是針對以後的新塊起效,以前的塊如果想生效,需要在新參數下,重整表資料,如重建該表,或者move該表。
需要同時修改一個block資料的session超過maxtrans參數的限制, 或者由于block空間使用過多導緻資料庫無法擴充itl, 就會發生itl的等待了。
如果itl已經重用,那如何進行一緻性讀?
ORACLE通過ITL條目中記錄的復原段位址找到復原段,實作讀一緻性,如果事務已送出,ITL就可以被重用,但是若前一個ITL被重用,前一個ITL的讀一緻性是如何實作的呢?
假定block隻有一個itl,假定第一個事務的時候産生了 ITL-0 (即第一個itl)
第二個事務來了,産生了 ITL-1 ,ITL-1 裡面的UBA (undo block address)可以找到復原段位址,復原段中除了記錄了 block使用者資料的 before image 外還記錄了 ITL-0 的資訊。
第三個事務來了,産生了 ITL-2 , ITL-2 中 UBA 指向復原段,復原段中 也記錄了 ITL-1 的資訊。
這樣當一個查詢若需要ITL-0時候的資訊,則找到目前block,發現是 ITL-2 ,根據UBA找到復原段進行 roll 得到 變化前 block ,這個時候發現block中是 ITL-1 . 還不能滿足需求。 于是再根據 ITL-1 中的 UBA 又去復原段中找到資料來進行roll,得到一個block 資料,這個時候block中就有了 ITL-0。
通過根據目前ITL進行遞歸的方式找到資料,實作之前ITL的獨一緻性。
行鎖原理:
Oracle的鎖機制是一種輕量級的鎖定機制,不是通過建構鎖清單來進行資料的鎖定管理,而是直接将鎖作為資料塊的屬性,存儲在資料塊首部。
這個是通過ITL來實作的,一個事務要修改塊中的資料,必須獲得該塊中的一個itl(通過initrans預先配置設定的或者是通過free space建構的)。通過itl和undo segment header(undo段的頭部)中的transaction table(事務表),可以知道事務處于活動階段(我覺得可以根據itl裡的flag列知道該事務是否是活動的),還是已經完成。
事務在修改塊時(其實就是在修改行)會檢查行中row header中的标志位,如果該标志位為0(該行沒有被活動的事務鎖住,這時可能要進行deferred block cleanout等工作),就把該标志位修改為事務在該塊獲得的itl的序号,這樣目前事務就獲得了對記錄的鎖定,然後就可以修改行資料了,這也就是oracle行鎖實作的原理。
3、事務中的儲存點:
儲存點(savepoint):在一個事務中可以設定任意多個儲存點,一般比較聰明的辦法就是在一個事務的每個函數開始前設定一個儲存點,這樣假如這個函數執行失敗,那麼就可以恢複到這個函數之前的儲存點,之前的資料不會被改變。回到儲存點時,之前的表級鎖行級鎖都會存在,但是剛剛傳回的那部分的鎖将釋放。
4、分布式事務和自治事務:
分布式事務(distributed transaction)指同一個事務(transaction)中的一個或多個 SQL 語句同時更新(update)分布式資料庫(distributed database)中不同節點(node)的資料。
兩步送出機制(two-phase commit mechanism)可以保證所有參與分布式事務(distributed transaction)的資料庫或者同時送出(commit),或者同時撤銷(undo)事務中 SQL 語句的操作。兩步送出機制還確定了由完整性限制(integrity
constraint),遠端過程調用(remote procedure call),及觸發器(trigger)執行的隐式 DML 操作正常工作。Oracle 兩步送出機制(two-phase commit mechanism)對于送出分布式事務(distributed transaction)的使用者來說完全透明。使用者甚至無需知道其事務是分布式的。當事務由一個 COMMIT 語句标志結束後會自動地觸發兩步式送出機制來送出此事務。資料庫應用程式中無需使用任何代碼或複雜的
SQL 文法就能處理分布式事務。
背景程序(recoverer,RECO)能夠自動地處理系統中出現的不可信的分布式事務(in-doubt
distributed transaction)。不可信的分布式事務指因為各種系統或網絡故障而阻礙了送出(commit)操作的分布式事務。當故障修複,通信恢複後,每個 Oracle 資料庫本地的 RECO 程序将自動地送出(commit)或復原(roll back)不可信的分布式事務,并保證所有參與分布式事務的節點協調一緻。
如果系統中的故障暫時無法恢複,Oracle允許資料庫 DBA 在本地手工地送出(commit)或撤銷(undo)此故障導緻的不可信的分布式事務(in-doubt
distributed transaction)。這個功能使本地的 DBA 可以釋放被不可信的分布式事務鎖住的資源
如果一個分布式環境中的資料庫需要恢複(recovery),其他節點的 DBA 可以使用 Oracle 的恢複功能将他們各自管理的資料庫也恢複到相同的時間點。這個功能保證了分布式環境中所有資料庫的資料一緻性(consistent)。
使用者可以通過 pragma 指令 AUTONOMOUS_TRANSACTION 将一個 PL/SQL 程式結構設定為自治事務(autonomous transaction)。pragma 是一個編譯器指令(compiler directive)。使用者可以将以下類型的 PL/SQL
程式結構定義為自治的:
伺服器端(stored)的過程(procedure)或函數(function)
本地的(local)過程或函數
包(package)
類型方法(type method)
頂級匿名塊(Top-level anonymous block)
自治 PL/SQL 程式結構内的事務控制語句(transaction control statements)僅對目前的自治事務(autonomous transaction)有效。這些控制語句包括:
SET TRANSACTION COMMIT ROLLBACK SAVEPOINT ROLLBACK TO SAVEPOINT
5、自治事務與内嵌事務的差別:
自治事務雖然是由别的事務啟動,但是它也不是一個内嵌事務,具體差別如下:
1、自治事務不會和主事務分享資源,如:鎖。
2、不會受制于主事務,如:主事務復原,内嵌事務就會復原,但是自治事務就不會復原。
3、自治事務送出改變對于别的事務是立即可見的,但是對于内嵌表,隻有等到主事務送出了之後才能可見。
4、在自治事務中得exceptions 是事務級别的復原,不是一個聲明級别的復原。
注意:
1、如果一個自治事務視圖去讀取一個主事務持有的資源,一個死鎖就這樣誕生了。。。這時,oracle産生一個exception,如果此異常不被捕獲,那就復原這個自治事務。
2、oracle初始化 TRANSACTIONS 參數的時候會聲明最大的并行事務數量。這個值在自治事務與主事務一塊運作(我估計是和别的主事務,自己也沒搞懂啊)的話可能要超出。
3、如果試圖讓一個還沒有復原或者送出的事務退出,oracle就會産生一個異常。如果異常不能被捕獲,那就復原事務。