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