oracle學習之undo的基本知識及事務與undo、數據塊的關聯


通過自己學習總結的這些undo知識能夠讓大家都能深刻了解oracle的undo相關原理。

一、undo撤銷表空間的作用

撤銷表空間通常稱為undo表空間:undo表空間的段也稱為撤銷段或undo段、回滾段;撤銷段中存放的數據就是撤銷信息,這些撤銷信息也稱為撤銷數據或undo數據。撤銷段是最直接管理撤銷新的邏輯層。

1.1、讀寫一致性

在不同的進程或用戶模式下檢索數據時,oracle只能給用戶提供被提交的數據,這樣可以確保數據的一致性。某個連接登錄到數據庫對某個表某個行進行update操作時未提交,其他連接查詢該行數據只能查詢到該行被改變之前的數據。具體實現的過程是undo段中記錄該行數據的鏡像,第二個連接上來,在buffer中找一個塊,從Undo回滾段中找出前面的鏡像,加上該行所在塊其他未修改的行,合成一個塊一起構造成cr塊,我們叫它構造cr塊,保證一致性讀。

1.2、可以回滾事務

當執行修改操作如insert、delete、update操作時,舊的數據被存放到undo段中,新的數據(臟數據)在沒被dbwr寫到數據文件時是存放在數據文件的塊所對應的buffer塊中。如果影虎不想完成之前的操作就可以回滾,rollback進行回滾。

1.3、事務恢復

事務恢復是實例恢復的一部分,他是oracle服務器自動完成的,如果數據庫在運行過程中出現實例失敗如斷電等,那么當重啟oracle服務時,后天進程smon進程會自動執行實例恢復,在恢復的過程中,跑日志前滾並回滾未提交的事務。

1.4、閃回操作

11g新增了強大的閃回功能,其中很多閃回技術都是基於undo段實現的,比如閃回表,閃回事務查詢,閃回版本查詢。

 

二、undo段的初始化參數

2.1、undo_tablespace

該參數用於指定實例所要使用的undo表空間,使用自動undo管理時,通過配置該參數指定實例所使用的undo表空間。如果auto模式沒有指定第一參數的話,oracle會自動選擇第一個可用的undo表空間來存放undo數據,如果沒有可用的undo表空間的話,oracle會使用system表空間存放undo數據,並在alter日志中告警。

 

2.2、undo_management

該參數用於指定undo表空間的管理模式,如auto自動管理模式,manual則為手動管理模式。

 

2.3、undo_retention

該參數用於控制undo數據最大保留事假,默認是900秒即為15分鍾。從9i開始配置該參數指定保留時間,這個參數我是這么理解的,事務A的回滾段(已提交,該回滾段為inactive),當數據庫的事務不是特比多或者基本沒有其他事務,A事務undo數據可以被保存很長時間,當數據庫的事務正常,可能15分鍾的時候被覆蓋,也可能20分鍾被覆蓋,但是當數據庫事務繁忙,undo表空間沒有空余的free expired的空間的話,A事務對應的回滾段數據可能第5分鍾就被覆蓋了。如果需要固定必須15分鍾后才被覆蓋的話,可以設置參數,

alter tablespace undotbs1 retention guarantee,則此時無法使用Inactive的undo段,如果沒有free,則自動擴展,如不能擴展則優先使用expired,但是此時設置了retention guarantee,無法使用inactive,此時數據庫容易產生ora-30035。我們可以通過下面語句查詢回滾段信息:

select segment_name,tablespace_name,status from dba_undo_extents;

free --沒有分配給任何段

active---區中有事務沒有提交

inactive--區中有事務已提交,但是沒有超過undo_retention時間

expired---事務提交了,也超過undo_retention時間

 

三、事務跟undo的關聯

1、事務表

oracle在undo表空間的段中的第一個塊存在一個事務表,事務表最多有47行,每一行可以放一個事務。當一個事務開始的時候,oracle給它分配一個xid事務編號,這個時候這個事務會做的第一件事就是在undo表空間找一個段,在段頭塊中找一行,把自己的事務信息寫上,至少寫上xid。oracle一個事務盡量使用一個回滾段,如果事務太多回滾段太少,這時會出現多個事務使用一個回滾段,oracle盡量均勻的將活動的事務分布在各個回滾段。總結:事務表在undo段中的一個數據塊中,每一個回滾段最多同時可以有47個活動的事務。

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

 

2、回滾段的段頭塊

數據庫有多少回滾段

select * from v$rollname;

可以用以上的sql查看,當前有查詢結果出來的這么多段頭塊,根據undo的負載情況系統會自動增加undo的段頭塊數量。查詢段頭塊地址:

 

select header_block,header_file from dba_segments where segment_name='_SYSSMU1_3086899707$';

 

HEADER_BLOCK HEADER_FILE

 

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

 

         128           3
上面的結果就是3號文件的第128個塊,3號文件就是undo的表空間文件。我們可以把這個段頭塊給dump出來,並進行查看
alter system dump undo header '_SYSSMU1$';
上面執行成功后,我們查詢下我們當前連接的進程號:
SQL> select spid from v$process where addr in (select paddr from v$session where sid=(select sid from v$mystat where rownum=1));
SPID
------------------------
5632
然后去oracle軟件的安裝目錄去查找*_ora*5632.trc,在Windows下可以編輯查看,Undo Segment:  _SYSSMU1_3086899707$ (1)就是這個段頭塊的信息,TRN TBL::就是事務表的信息。( alter system dump datafile 5 block 4308;//轉儲數據塊)
 
3、undo的位置信息
實例在三個地方有undo的信息:undo segment header回滾段段頭塊,data block header數據塊塊頭,undo block回滾塊上。
一個事務開始,先找一個回滾段,在回滾段段頭塊的事務表中找一個空的事務槽位,寫上事務信息如xid。事務的基礎還有一個就是事務槽,一個事務可以修改一個數據塊,數據塊上有事務槽,一個數據塊有多個事務槽,1-255,修改一個數據塊,首先這個事務要在數據塊頭部的事務槽找一個空的槽位寫上事務信息。
根據前面這兩點,我們知道了,一個事務開始以后,首先在undo表空間找到一個回滾段,在回滾段的段頭塊的事務表寫上一行事務信息,在要修改的數據塊頭部的事務槽上寫上事務信息。關於事務信息為什么要在上面說的兩個地方寫上和oracle事務的一種提交方式有關。
undo數據塊的地址:oracle要修改數據塊的話,要將數據塊修改前的數據存到回滾塊里去,回滾塊是實實在在存數據的,而事務表跟數據塊的事務槽都是存事務信息的,所以回滾塊會有很多。
 
4、事務表、事務槽、回滾塊的關系
一個事務開始的時候,首先oracle做一件事情,在undo表空間上找一個相對空閑的undo段的段頭塊的事務表上找一個空的槽位,在上面寫上事務信息。同時給這個事務分配一個undo塊,同時將undo塊的地址寫到事務表里,即UBA地址。以上第一步是找回滾段段頭里的事務表,在事務表里寫上XID,同時分配一個undo塊,並在剛才的事務槽上寫上UBA地址。第二步要實實在在的修改數據了,要修改數據塊,首先在要修改的數據塊的頭部事務槽里找到一個空的槽位,把XID寫上,接着修改數據塊,比如修改了三行數據,修改數據以后就需要把修改前的數據保存到undo塊里面去,針對這個事務的Undo塊已經分配了,就把修改前的數據寫到undo塊里去,同時數據塊的事務槽里也寫上UBA地址,他指向回滾塊。
 
 
5、xid事務id
xid (transaction identifier 或transaction id)
事務的xid即是事務編號,也是一個地址,它代表着這個事務用哪個回滾段,
xid的信息內容包括:使用了哪個回滾段段頭,段頭塊的事務表有47行該事務使用的是哪一行,所在的槽位是第多少次被使用(第多少次被覆蓋),所以說xid有三塊內容組成,塊號、行號和覆蓋次數,這就是確定了這個事務的唯一性。
 
6、事務流程中的事務信息
回顧一下,第一步:一個事務開始oracle做的第一件是,在undo表空間里找到一個相對空閑的undo段,找到回滾段段頭塊里的事務表,在事務表里找到其中一行,把事務信息寫上,除了在事務表找到一個槽位,還要在回滾段里找到一個undo塊,讓事務表中的槽位指向這個塊。
第二步,這時要修改具體的數據塊,首先在數據塊的頭部的事務槽里找一行,然后在事務槽寫上xid,這個事務編號就相當於指向了undo頭部事務表中的那個記錄,因為xid是地址,通過地址就能找到事務表。
第三步:然后對數據塊進行修改,修改了幾行,就把這幾行原理的數據寫到回滾塊里面。同時數據塊的事務槽有地址指向這個回滾塊。這個事務修改了一個塊,還可以修改第二個塊,可以修改多個塊。第一個塊修改完了,修改第二個數據塊,也是上面步驟,如果這個時候undo塊滿了,再分配一個回滾塊,然后把數據塊的修改前的信息寫進去,第二個數據塊的事務槽又指向新的回滾塊,兩個回滾塊有先后關系,有最早的回滾信息和最新的回滾信息,新的回滾塊指向早的回滾塊,把兩個塊鏈起來,就是新的回滾塊有個鏈指向老的回滾塊。也就是找到最新的回滾信息可以依次向前退,這時事務表的uba就指向這個事務最新的回滾塊。這樣的操作可以繼續修改新的塊,分配新的undo回滾塊。每個數據塊指向自己對應修改時最新的回滾塊,最新的修改的數據塊中的Uba指向最新的回滾塊,事務表的uba指向最新的回滾塊。
 
7、uba的指向及作用
undo段段頭塊有事務表,事務表的事務槽上有xid和uba,回滾段事務表中事務槽的Uba指向最新的undo塊,比如一個事務產生有三個回滾塊,有最新的回滾塊,有其次新的,有最老的回滾塊,一個事務的回滾塊自動地串起來。數據塊的塊頭部都有個xid使數據塊指向事務表,一個事務的所有數據塊頭部的xid都指向回滾段段頭事務表的一行數據。修改的某一個數據塊,修改前的數據存放到一個回滾塊里,各個數據塊里面的uba都指向各自修改時的回滾塊,一個事務對應undo段段頭塊事務表里的Uba指向該事務最新的那個回滾塊。
 
7.1、事務表中Uba的作用
假設一個事務修改了三個數據塊,先修改了第一個塊,再修改第二個塊,又修改了第三個塊。要回滾的時候,要先把第三個塊的數據回滾,再回滾2再回滾1號的。修改的時候是123,回滾的時候是321反着來。undo段頭事務表中這個事務Uba指向最新的回滾塊,要回滾的時候,根據事務表中的Uba找到最新的,先把最新的回滾塊回滾,因為最新的回滾塊有個地址指向該條事務的前一個回滾塊,這個指向了第二個再把第二個回滾塊回滾了,第二個回滾塊又指向了第一個回滾塊,這里再把最早的一個回滾塊回滾了,回滾完了,第一個回滾塊不指向任務塊了,表示這個事務回滾完了。
oracle做rollback的時候會這樣做:
首先在事務表里找到這個要回滾的事務,然后找到uba,根據uba找到最新的回滾塊,把對應的數據回滾了,在這個回滾塊中記錄了該條事務的上一個回滾塊,找到上一個回滾塊,然后使用這個回滾塊回滾對應的數據塊,然后在使用最早的回滾塊把它對應的數據塊回滾了,這樣就回滾完了,rollback完成。
 
7.2、數據塊事務槽中uba的作用
數據塊中的事務槽中有一個地址指向一個回滾塊,有直接指向的意義,數據塊事務槽中的uba直接指向回滾塊,是數據塊實實在在的指向它自己的回滾數據。一個數據塊要找回回滾數據的話,第一種方法可以直接拿過來,從數據庫的事務槽uba信息直接找到回滾塊。第二種方法從數據塊事務槽找到undo段頭事務表中對應的事務信息,再找到undo塊。-----數據塊單獨有地址指向回滾數據,這個鏈短,在要進行cr讀、讀一致性的時候有好處,讀數據塊的時候,發現這個塊有未提交的事務,就需要構造cr塊,就在buffer cache中找一個空塊,把數據塊和undo塊信息合起來,拼成一個新塊,然后讀這個塊。所以數據塊直接寫上對應的undo的uba地址,直接讀數據塊和對應回滾塊兩個塊就拼成一個CR塊,不需要讀段頭事務表了。
 
8、事務信息的鏈的意義
undo segment header和data block header 和undo block的事務信息之間有很多鏈,有很多的地址,他們的意義是:
1、rollback
在回滾段的段頭塊里面有事務有事務信息和uba地址,事務表uba地址指向事務最后一個undo塊,最后一個undo塊又串着前一個undo塊,又向前串着上一個undo塊,主要是為了rollback回滾做准備。
2、構造cr塊讀
數據塊的事務槽有uba直接指向undo塊回滾數據,為了一致性讀ce做准備。
3、快速提交
數據塊xid還要指向undo段頭的事務表,如果一個事務快速提交時未清理這個事務對應數據塊事務槽中的相關信息,再有其他操作需要修改這個數據塊中前面這個事務已經修改的數據行時,在事務槽不能確定這個事務的提交狀態,就需要通過這個事務找到這個事務表中對應的行,來最終確定前面這個事務的提交狀態,所以需要這種指向鏈。也就是數據塊事務槽xid信息。
 
9、關於本節的總結,務必掌握
下面描述下事務的修改過程
1、第一步
一個事物開始,首先在undo表空間里面找相對空閑的undo段的段頭塊的事務表里的一行,將自己的xid寫上,同時在undo段里面分配一個空塊作為回滾塊,同時將回滾塊的地址寫到事務表的事務槽里。
2、第二步
要修改具體的數據了
修改任何一個數據庫都是要在數據塊塊的頭部獲取一個事務槽,然后寫上xid,獲取到事務槽就開始修改數據塊,修改數據塊的時候,還將修改前的數據寫到回滾塊里,因為這個事務已經分配一個回滾塊了,就直接寫到回滾塊里面去,同時將這個數據塊所對應的回滾塊的地址也寫到數據塊的事務槽里,回滾數據寫完了,接下來修改實實在在的行,第一個數據塊修改完了,再修改第二個數據塊,同樣的操作繼續修改數據塊,同時如果這個時候一個回滾塊不夠,要分配第二第三個回滾塊,同是一個事務的回滾塊之間要串起來,由新到舊的指向,同時如果加了回滾塊,會把最新的回滾塊信息uba地址寫到該事務的事務表里。
以上是整個事務的操作流程,這三個回滾塊串起來以及事務表的uba指向最新的回滾塊,這樣為了更方便的回滾。在每個數據塊里面,直接寫uba指向自己的undo數據塊,為了更方便的構造cr塊及一致性讀。同時,一個事務信息在兩個位置都有,數據塊的事務槽里有,undo段頭塊的事務表里有,數據塊的事務槽指向事務表,這個和Oracle的一種提交方式有關!
一個事務開始以后,Oracle修改了四個地方:
回滾段的段頭塊的事務表被修改;
回滾塊被修改;
數據塊的事務槽被修改;
數據塊的數據行被修改。
這四個地方的數據都在數據塊里面,數據塊的任務地方的改變都會產生redo,redo不僅僅記錄的是數據行的改變,事務槽的改變、undo塊的改變、事務表的改變一樣都會產生redo,這就是一個事務的操作流程。
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM