為了保證數據庫中多個用戶間的讀一致性和能夠回退事務。
一、在一個簡單的更新語句中,對於回滾段的操作存在多處,在事務開始時,首
先需要在回滾表空間獲得一個事務槽,分配空間,然后創建前鏡像,此后事務的
修改才能進行,oracle必須以此來保證事務是可以回滾的。如果用戶提交了事務
,oracle會在日志文件記錄提交,並且寫出日志,同時會在回滾段中把事務標記
為已提交;如果用戶回滾事務,則oracle需要從回滾段中把前鏡像數據讀取出來
修改數據緩沖區,完成回滾,這個過程本身也要產生redo,所以回退這個操作是
很昂貴的。
二、回滾段存儲的內容
1、對於insert 操作,回滾段只需要記錄插入記錄的rowid,如果回退,只
需要將該記錄根據rowid刪除即可。
2、對於update操作:回滾段只需要記錄被更新字段的舊值即可,回退時通
過舊值覆蓋新值即可完成回退。
3、對於delete操作,oracle則必須記錄正行的數據,在回退時,oracle通
過一個反向操作恢復刪除的數據。
三、並發控制和一致性讀
1、一方面oracle通過鎖定機制實現數據庫的並發控制;一方面通過多版本
模型來進行並發數據訪問。通過多版本架構,oracle實現了讀取和寫入的分離,
使得寫入不阻塞讀取,讀取不阻塞修改。這是oracle數據庫區別於其他數據庫的
一個重要特征。oracle一方面不允許其他用戶讀取未提交數據,一方面要保證用
戶讀取數據要來自同一時間點。
假設員工scott的薪水為3000那么:
1)在t1時間,在session1查詢可以得到這個結果
2)在t2時間session2進行更新,將scott的薪水增加3000,並為提交
3)在t3時間session1再次查詢,注意此時,oracle不會允許其他用戶看到未提交數據,所以此時,oracle需要通過回滾段記錄的前鏡像進行一致讀,將3000恢復出來供給用戶,這是一致性讀的作用。
4)在t4時間,session2提交更改,此時數據修改被永久化;
5)在t5時間,其他用戶再次查詢,將會看到變化后的數據,也就是4000.
oracle內部使用scn作為時鍾,在這里查詢結果集就是根據scn來進行判斷的,每個數據塊頭部都會記錄一個提交scn,當數據更改提交后,提交scn同時被修改,這個scn在查詢時可以用來進行一致性讀判斷。
四、在自動undo管理表空間,oracle隨之引入了幾個新的初始化參數
undo_management:用來定義數據塊使用的回滾段是否使用自動管理模式。該參數有兩個選項,auto表示自動管理,manual表示手工管理。
undo_tablespace:用來定義在自動管理模式下,當前實例使用哪個undo表空間。
undo_retention:表示在自動管理模式下,當回滾段變得非激活之后,回滾段中的數據在被覆蓋前保留的時間,該參數單位是秒。
五、回滾機制的深入研究
1、獲取事務信息:
v$transaction動態視圖
xidusn:回滾段號
xidslot:事務槽
xidsqn:事務的序列號
ubafil:undo block address filenum
ubablk:UBA block number
ubarec:UBA record number
v$rollstat動態視圖
usn:回滾段標識
rssize:回滾段默認大小
xacts:活動事務數
writes:回滾段寫入數
shrinks:回滾段收縮次數
extends:回滾段擴展次數
gets:獲取回滾段頭次數
waits:回滾段頭等待次數
2、轉儲undo段
在undo段頭的轉儲文件中,dba指向的就是包含這個事務的前鏡像的數據塊地址。前十位代表文件號,后22位代表block號。轉儲文件中的irb:指的是回滾段中記錄的最近未提交變更開始之處,如果回滾,這是起始的搜索點。rci:該參數代表的是undo chain(同一事務中的多次修改,根據chain連接關聯)的下一個偏移量。在x$BH中class字段中4表示的是段頭,1表示的是數據塊,state為3的就是一致讀構造的前鏡像。
select b.segment_name ,a.file#,a.dbarfil,a.dbablk,a.class,a.state
from x$bh a,dba_extents b
where b.relative_fno=a.dbarfil
and b.block_id<=a.dbablk
and b.block_id+b.blocks>a.dbablk
and b.owner='SCOTT'
and b.segment_name='EMP'
3、轉儲數據塊信息
ITL事務槽指interested transaction list,事務必須獲得一個ITL事務槽才能夠進行數據修改ITL內容包括:
xid:事務的id
uba:undo塊的地址
lck:lock status
xid=undo.segment.number+transaction.table.slot.number+wrap
事務的內部流程
1)首先當一個事務開始時,需要在回滾段事務表上分配一個事務槽
2)在數據塊頭部獲取一個ITL事務槽,該事務槽指向回滾段頭的事務槽
3)在修改數據之前,需要記錄前鏡像信息,這個信息以undo record的形式存儲在回滾段中,回滾段頭事務槽指向該記錄。
4)鎖定修改行,修改行鎖定位指向ITL事務槽。
5)數據修改可以進行。
4、塊清除(block cleanouts)
在事務需要修改數據時,必須分配ITL事務槽,必須鎖定該行,必須分
配回滾段事務槽和回滾空間記錄前鏡像。當事務提交時,oracle需要將回滾段上
的事務表信息標記為非活動,以便空間可以重用;那么還有ITL事務信息和鎖定信
息需要清除,以記錄提交。由於oracle在數據塊上存儲了ITL和鎖定等事務信息,
所以oracle必須在事務提交之后清除這些事務數據,這就是塊清除。塊清除主要
清除的數據有行級鎖、ITL信息(包括提交標志、SCN等)。如果提交時修改過的
數據塊仍然在buffer cache之中,那么oracle可以清除ITL信息,這叫做快速塊清
除,如果事務提交時修改過的數據塊已經被寫回到數據文件上,oracle會等到下
次訪問該block時再來清除ITL鎖定信息,這就是延遲塊清除。
5、產生ora-01555錯誤的原因
1)由於回滾段是循環使用的,當事務提交以后,該事務占用的回滾事務表被標記為非活動,回滾段空間可以被覆蓋重用。那么當一個查詢需要使用被覆蓋的回滾段構造前鏡像實現一致讀,此時就會出現oracle著名的ora-01555錯誤
2)因為延遲塊清除。當一個查詢觸發延遲快清除時,oracle需要去查詢回滾段獲得該事務的提交scn,如果事務的前鏡像信息已經被覆蓋,並且查詢scn也小於回滾段中記錄的最小scn,那么oracle將無法判斷查詢scn和事務提交scn的大小,此時就會出現延遲塊清除導致的ora-01555錯誤。
3)使用sqlldr直接加載數據時。
alter tablespace tablespace_name retention guarantee;
oracle提供一個內部事件(10203事件)可以用來跟蹤數據庫的塊清除操作,10203事件可以通過以下命令設置,設置后需要重新啟動數據庫該參數才能生效
alter system set event="10203 trace name context forever" scope=spfile;
alter database datafile '.....' offline drop;
六、回滾段的空間過大
1)通過查詢試圖v$dba_data_file和v$dba_temp_files確定臨時表空間和undo表空間的大小
2)新建一個undo表空間
create undo tablespace tablespace_name;
3)切換undo表空間
alter system set undo_tablespace=undotbs2 scope=both;
4)等待原表空間所有undo segment offline;
5)刪除原undo表空間
drop tablespace undotbs1 including contents;
七、特殊情況的恢復
在很多情況下,特別是在使用隱含參數強制打開數據庫之后,可能會在ora-006004194錯誤,在alert文件中,記錄主要錯誤日志,出現此種錯誤時,最好的辦法是通過備份進行恢復,如果沒有備份,那么可以通過特殊的初始化參數進行強制啟動,
1)從當前的日志文件中找到對應的AUM(auto undo management)下的回滾段名稱。
2)修改init<sid>.ora參數文件,使用oracle隱含參數_corrupted_rollback_segments將回滾段標記為損壞,oracle會跳過對於這些回滾段的相關操作,強制啟動數據庫。
3)使用init<sid>.ora參數文件啟動數據庫
startup pfile=initconner.ora
4)重新創建新的undo表空間,刪除出現問題的表空間,修改參數文件,由參數文件生成新的spfile,重新啟動數據庫。
create undo tablespace undotbs1 datafile '.......' size 10m;
alter system set undo_tablespace=undotbs1 scope=both;
drop tablespace undotbs2;
修改參數文件,變更undo表空間,並取消_corrupted_rollback_segments設置。
有參數文件創建spfile;
打開數據庫即可;