ORACLE的工作機制.docx_第1頁
ORACLE的工作機制.docx_第2頁
ORACLE的工作機制.docx_第3頁
ORACLE的工作機制.docx_第4頁
ORACLE的工作機制.docx_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

ORACLE的工作機制-1肖亞峰(xyf_tck)我們從一個用戶請求開始講,ORACLE的簡要的工作機制是怎樣的,首先一個用戶進程發(fā)出一個連接請求,如果使用的是主機命名或者是本地服務(wù)命中的主機名使用的是機器名(非IP地址),那么這個請求都會通過DNS服務(wù)器或HOST文件的服務(wù)名解析然后傳送到ORACLE監(jiān)聽進程,監(jiān)聽進程接收到用戶請求后會采取兩種方式來處理這個用戶請求,下面我們分專用服務(wù)器和共享服務(wù)器分別采用這兩種方式時的情況來講:專用服務(wù)器模式下:一種方式是監(jiān)聽進程接收到用戶進程請求后,產(chǎn)生一個新的專用服務(wù)器進程,并且將對用戶進程的所有控制信息傳給此服務(wù)器進程,也就是說新建的服務(wù)器進程繼承了監(jiān)聽進程的信息,然后這個服務(wù)器進程給用戶進程發(fā)一個RESEND包,通知用戶進程可以開始給它發(fā)信息了,用戶進程給這個新建的服務(wù)器進程發(fā)一個CONNECT包,服務(wù)器進程再以ACCEPT包回應(yīng)用戶進程,至此,用戶進程正式與服務(wù)器進程確定連接。我們把這種連接叫做HAND-OFF連接,也叫轉(zhuǎn)換連接。另一種方式是監(jiān)聽進程接收到用戶進程的請求后產(chǎn)生一個新的專用服務(wù)器進程,這個服務(wù)器進程選用一個TCP/IP端口來控制與用戶進程的交互,然后將此信息回傳給監(jiān)聽進程,監(jiān)聽進程再將此信息傳給用戶進程,用戶進程使用這個端口給服務(wù)器進程發(fā)送一個CONNECT包,服務(wù)器進程再給用戶進程發(fā)送一個ACCEPT包,至此,用戶進程可以正式向服務(wù)器進程發(fā)送信息了。這種方式我們叫做重定向連接。HAND-OFF連接需要系統(tǒng)平臺具有進程繼承的能力,為了使WINDOWS NT/2000支持HAND-OFF必須在HKEY_LOCAL_MACHINESOFTWAREORACLEHOMEX中設(shè)置USE_SHARED_SOCKET。共享服務(wù)器模式下:只有重定向連接的方式,工作方式是監(jiān)聽進程接收到用戶進程的請求后產(chǎn)生一個新的調(diào)度進程,這個調(diào)度進程選用一個TCP/IP端口來控制與用戶進程的交互,然后將此信息回傳給監(jiān)聽進程,監(jiān)聽進程再將此信息傳給用戶進程,用戶進程使用這個端口給調(diào)度進程發(fā)送一個CONNECT包,調(diào)度進程再給用戶進程發(fā)送一個ACCEPT包,至此,用戶進程可以正式向調(diào)度進程發(fā)送信息了。可以通過設(shè)置MAX_DISPIATCHERS這個參數(shù)來確定調(diào)度進程的最大數(shù)目,如果調(diào)度進程的個數(shù)已經(jīng)達到了最大,或者已有的調(diào)度進程不是滿負荷,監(jiān)聽進程將不再創(chuàng)建新的調(diào)度進程,而是讓其中一個調(diào)度進程選用一個TCP/IP端口來與此用戶進程交互。調(diào)度進程每接收一個用戶進程請求都會在監(jiān)聽進程處作一個登記,以便監(jiān)聽進程能夠均衡每個調(diào)度進程的負荷,所有的用戶進程請求將分別在有限的調(diào)度進程中排隊,所有調(diào)度進程再順序的把各自隊列中的部分用戶進程請求放入同一個請求隊列,等候多個ORACLE的共享服務(wù)器進程進行處理(可以通過SHARED_SERVERS參數(shù)設(shè)置共享服務(wù)器進程的個數(shù)),也就是說所有的調(diào)度進程共享同一個請求隊列,共享服務(wù)器模式下一個實例只有一個請求隊列,共享服務(wù)器進程處理完用戶進程的請求后將根據(jù)用戶進程請求取自不同的調(diào)度進程將返回結(jié)果放入不同的響應(yīng)隊列,也就是說有多少調(diào)度進程就有多少響應(yīng)隊列,然后各個調(diào)度進程從各自的響應(yīng)隊列中將結(jié)果取出再返回給用戶進程。以上我們講完了用戶與ORACLE的連接方式,下面我們要講ORACLE服務(wù)器進程如何處理用戶進程的請求,當一個用戶進程發(fā)出了一條SQL語句:UPDATE TABBLEA SET SALARY=SALARY*2;首先服務(wù)器進程將對該語句進行檢查語句有效性的語法檢查和確保語句能夠正常運行的語義檢查,首先檢查該語句的語法的正確性(語法檢查),接著對照數(shù)據(jù)字典對語句中涉及的表、索引、視圖等對象及用戶的權(quán)限進行檢查(語義檢查),如果以上任一檢查沒有通過,就返回一個錯誤,但不會明確的指出是語法檢查出錯還是語義檢查出錯,它只會返回一個ORA-*的錯誤碼。如果檢查通過以后,服務(wù)器進程把這條語句的字符轉(zhuǎn)換成ASCII等效數(shù)字碼(注意SQL中使用*是個例外,如果表的字段改變了,同樣是SELECT * FROM TABLEA轉(zhuǎn)換成的ASCII是不同的,其實它在語義檢查時就明確的變成了操作具體字段的SQL語句了),接著這個ASCII碼被傳遞給一個HASH函數(shù),并返回一個HASH值,服務(wù)器進程將到SHARED POOL的共享PL/SQL區(qū)去查找是否存在同樣的HASH值,如果存在,服務(wù)器進程將使用這條語句已高速緩存在SHARED POOL中的已分析過的版本來執(zhí)行(軟解析),如果不存在,則必須進行以下兩個步驟:語句的優(yōu)化(生成執(zhí)行計劃)和生成執(zhí)行編碼:服務(wù)器進程根據(jù)ORACLE選用的優(yōu)化模式以及數(shù)據(jù)字典中是否存在相應(yīng)對象的統(tǒng)計數(shù)據(jù)和是否使用了存儲大綱來生成一個執(zhí)行計劃或從存儲大綱中選用一個執(zhí)行計劃,最后再生成一個編譯代碼(硬解析)。(這里要注意的是,語法語義分析在前,計算HASH_VALUE在后,算出HASH_VALUE后只要找到相同的HASH_VALUE就使用這條緩存執(zhí)行計劃,語義分析在前確保了用戶的使用權(quán)限等問題,不存在算出HASH_VALUE,再找到相同HASH_VALUE緩存執(zhí)行計劃而不能使用的情況。也不是先算HASH_VALUE,然后找緩存執(zhí)行計劃,找到后再語義檢查這個步驟也是錯的)ORACLE將這條語句的本身實際文本、HASH值、編譯代碼、與此語句相關(guān)聯(lián)的任何統(tǒng)計數(shù)據(jù)和該語句的執(zhí)行計劃緩存在SHARED POOL的共享PL/SQL區(qū)。V$librarycache中的幾個參數(shù)解釋Pins: (Execution)即SQL實際執(zhí)行的次數(shù),不包括用戶提交的語法語義檢查失敗的SQL。Reloads: (Parse)未找到相同HASH_VALUE的次數(shù),即必須進行硬解析的次數(shù)。Invalidations: (Parse)因?qū)ο蟾?,使得所有引用這個對象的緩存執(zhí)行計劃失效而必須再次硬解析的次數(shù)。只要DDL更改了一個對象,所有與此有關(guān)的緩存在共享池中執(zhí)行計劃都將立即失效,它的失效不是在下次執(zhí)行SQL時才發(fā)現(xiàn)其失效,而是DDL更改對象后立即就失效。主要表現(xiàn)在DDL發(fā)生后v$sql的HASH_VALUE仍保持不變,但PLAN_HASH_VALUE立即變?yōu)?,再次運行SQL語句時則會向v$sql插入一條新的緩沖記錄HASH_VALUE,PLAN_HASH_VALUE都重新計算。原來的緩沖記錄仍然還存在。服務(wù)器進程通過SHARED POOL鎖存器來申請可以向哪些共享PL/SQL區(qū)中緩存這些內(nèi)容,也就是說被SHARED POOL鎖存器鎖定的PL/SQL區(qū)中的塊不可被覆蓋,因為這些塊可能正在被其它進程所使用。在SQL分析階段將用到LIBRARY CACHE,從數(shù)據(jù)字典中核對表、索引、視圖及用戶的權(quán)限的時候,需要將數(shù)據(jù)字典從磁盤讀入LIBRARY CACHE,因此,在讀入之前也要使用LIBRARY CACHE鎖存器來申請用于緩存數(shù)據(jù)字典。ORACLE的工作機制-2肖亞峰(xyf_tck)生成編譯代碼之后,接著下一步服務(wù)器進程要準備開始更新數(shù)據(jù),服務(wù)器進程將到DB BUFFER中查找是否有相關(guān)對象的緩存數(shù)據(jù),下面分兩個可能進行解釋:如果沒有,服務(wù)器進程將在表頭部請求一些行鎖,如果成功加鎖,服務(wù)器進程將從數(shù)據(jù)文件中讀入這些行所在的第一個數(shù)據(jù)塊(db block)(DB BLOCK是ORACLE的最小操作單元,即使你想要的數(shù)據(jù)只是DB BLOCK中很多行中的一行或幾行,ORACLE也會把這個DB BLOCK中的所有行都讀入DB BUFFER中)放入DB BUFFER中空閑的區(qū)域或者覆蓋已被擠出LRU列表的非臟數(shù)據(jù)塊緩沖區(qū),并且排列在LRU列表的頭部,如果這些非臟數(shù)據(jù)緩沖區(qū)寫完也不能滿足新數(shù)據(jù)的請求時,會立即觸發(fā)DBWN進程將臟數(shù)據(jù)列表中指向的緩沖塊寫入數(shù)據(jù)文件,并且清洗掉這些緩沖區(qū),來騰出空間緩沖新讀入的數(shù)據(jù),也就是在放入DB BUFFER之前也是要先申請DB BUFFER中的鎖存器,成功鎖定后,再寫入DB BUFFER,然后把這個塊的頭部事務(wù)列表及SCN信息及被影響的行數(shù)據(jù)原值寫入回滾段中,以便ORACLE在ROLLBACK時可以利用當前數(shù)據(jù)塊和回滾段重構(gòu)數(shù)據(jù)塊的前映像或遞歸重構(gòu)出前前映像來實現(xiàn)讀一致性。(回滾段可以存儲在專門的回滾表空間中,這個表空間由一個或多個物理文件組成,并專用于回滾表空間,回滾段也可在其它表空間中的數(shù)據(jù)文件中開辟。)然后在LOG BUFFER中生成日志,服務(wù)器程將該語句影響的被讀入DB BUFFER塊中的這些行的ROWID及將要更新的原值和新值及SCN等信息,以及回滾段的修改信息(即對某某回滾段地址進行了什么修改)逐條的寫入REDO LOG BUFFER,在寫入REDO LOG BUFFER之前也是先請求REDO LOG BUFFER塊的鎖存器,成功鎖定之后才開始把REDOLOG寫入REDOLOG BUFFER。當寫入達到REDO LOG BUFFER大小的三分之一或?qū)懭肓窟_到1M或超過三秒后或發(fā)生檢查點時或者COMMIT時或者DBWN之前觸發(fā)LGWR進程,LGWR將把REDO LOG BUFFER中的數(shù)據(jù)寫入磁盤上的重做日志文件,已被寫入重做日志文件的REDO LOG BUFFER中的塊上的鎖存器被釋放,并可被后來寫入的信息所覆蓋。回滾段其實也有BUFFER(在DB BUFFER中開辟),回滾段BUFFER中的內(nèi)容是最早向磁盤上回滾段中寫的,寫完這些才會生成日志BUFFER中的內(nèi)容,原因是日志中必須要記錄回滾段的新舊變化以便在恢復(fù)時從日志中的記錄的回滾段新舊變化對回滾段再次重寫,記住,REDO不光是對數(shù)據(jù)文件依據(jù)日志文件重寫,也要依據(jù)日志文件對回滾段重寫,而且重寫回滾段要先于重寫數(shù)據(jù)文件,要理解REDO就是重來一遍,所謂重來一遍就要跟正常的的先后順利一樣重做一遍(正常的操作中的順序就是先讀入DB BUFFER,寫回滾段buffer,后寫回滾段,后寫日志BUFFER,后改寫DB BUFFER,后寫日志最后寫數(shù)據(jù)文件)區(qū)別是REDO時不用再記日志了,這樣解釋后相信大家應(yīng)該理解為什么日志中也必須要記錄回滾段的信息了,只有這樣才可以對正常操作中的一個ROLLBACK動作進行恢復(fù),即在REDO過程中利用即時重寫的數(shù)據(jù)塊和回滾段重構(gòu)出一個當時適用的前鏡像來rollback。當一個重做日志文件寫滿后,LGWR將切換到下一個重做日志文件,重做日志文件也是循環(huán)工作方式。如果是歸檔模式,歸檔進程還將前一個寫滿的重做日志進程寫入歸檔日志文件。當DB BUFFER改寫之后,服務(wù)器進程在臟數(shù)據(jù)列表中建立一條指向此DB BUFFER緩沖塊的指針。接著服務(wù)器進程會從數(shù)據(jù)文件讀入第二個數(shù)據(jù)塊(db block)重復(fù)以上讀入,建立回滾段,寫LOG BUFFER,改寫DB BUFFER,放入臟列表的動作,當臟數(shù)據(jù)列表達到一定長度時,DBWN進程將臟數(shù)據(jù)列表中指向的緩沖塊全部寫入數(shù)據(jù)文件,也就是釋放加在這些DB BUFER塊上的鎖存器,并在修改相應(yīng)塊的頭部的SCN號(一次UPDATE操作只對應(yīng)一個SCN)。前面說過DBWN動作之前會先觸發(fā)LGWR,這用以確保寫入數(shù)據(jù)文件的改變首先會被記錄在日志文件中。實際上ORACLE可以從數(shù)據(jù)文件中一次讀入多個塊放入DB BUFFER,然后再對這些塊建回滾段、再記日志等等,也就是每次操作的對象是DB BLOCK的復(fù)數(shù),而不僅限于一次操作一個DB BLOCK,可以通過參數(shù)DB_FILE_MULTIBLOCK_READ_COUNT來設(shè)置一次讀入的塊的個數(shù)。注意,不管是否提交,用戶的所有更改都會被記錄在日志文件中,用戶級回滾的動作(rollback)沒有對應(yīng)的COMMIT SCN。在密集事務(wù)的情況下,LGWR可以把多個COMMIT產(chǎn)生的REDO條目批量寫入REDO LOG FILE,但每個COMMIT之間有十分之一秒的間隔,且會產(chǎn)生不同的COMMIT SCN。LGWR正常情況下是一個休眠進程,會被一定的條件觸發(fā),喚醒,比如COMMIT就是一個喚醒條件,一旦LGWR被喚醒,LGWR將把喚醒時間點之前LOG BUFFER中產(chǎn)生的所有內(nèi)容(從上次LGWR喚醒后到本次喚醒前之間寫入LOG BUFFER的內(nèi)容)寫入LOG FILE,直到LGWR完成后,LGWR才可以被再次觸發(fā),在LGWR觸發(fā)到完成期間所有對數(shù)據(jù)庫的操作仍然可以不間斷的加入LOG BUFFER。在這段時間內(nèi),LGWR不再接收其它條件的觸發(fā),比如緊跟前一個COMMIT之后的其它COMMIT(復(fù)數(shù))都要等待LGWR完成后才可以再次觸發(fā)LGWR,并在LGWR下次被觸發(fā)時,將積累的REDO BUFFER條目一次性寫入REDO LOG,后繼的COMMIT不會單個單個的觸發(fā)LGWR。如果要查找的數(shù)據(jù)已緩存,則根據(jù)用戶的SQL操作類型決定如何操作,如果是SELECT則查看DB BUFFER塊的頭部是否有事務(wù),如果有,將利用回滾段進行重構(gòu)出一致性塊再讀取,如果沒有則比較SELECT的SCN與DB BUFFER塊頭部的SCN如果比自己大,仍然同上,如果比自己小則認這是一個非臟緩存,可以直接從這個DB BUFFER塊中讀取。如果是UPDATE則即使在DB BUFFER中找到一個沒有事務(wù),而且SCN比自己小的非臟緩存數(shù)據(jù)塊,服務(wù)器進程仍然要到表的頭部對這條記錄申請加鎖,加鎖成功則進行后續(xù)動作,如果不成功,則要等待前面的進程解鎖后才能進行動作。ORACLE的工作機制-3肖亞峰(xyf_tck)只有當SQL語句影響的所有行所在的最后一個塊被讀入DB BUFFER并且重做信息被寫入REDO LOG BUFFER(僅是指重做日志緩沖,而非重做日志文件)之后,用戶才可以發(fā)出COMMIT,COMMIT觸發(fā)LGRW,但并不強制立即DBWN來釋放所有相應(yīng)的DB BUFFER塊上的鎖,也就是說有可能出現(xiàn)已COMMIT,但在隨后的一段時間內(nèi)DBWN還在寫這條語句涉及的數(shù)據(jù)塊的情形,表頭部的行鎖,并不是在COMMIT一發(fā)出就馬上釋放,實際上要等到相應(yīng)的DBWN進程結(jié)束才會釋放。一個用戶請求鎖定另一個用戶已COMMIT的資源不成功的機會是存在的。COMMIT發(fā)出后會將回滾段中的前映像標識為已提交.DML語句會產(chǎn)生一個SCN號,DBWN觸發(fā)時寫入到數(shù)據(jù)塊的頭部,COMMIT時也會產(chǎn)生一個SCN號,也會被寫入數(shù)據(jù)塊的頭部。在數(shù)據(jù)塊的頭部只存儲一個最新的SCN號,COMMIT之后這個事務(wù)插槽可以被另外一個事務(wù)使用。如果用戶ROOLBACK,則服務(wù)器進程會根據(jù)數(shù)據(jù)文件塊和DB BUFFER中塊的頭部的事務(wù)列表和SCN以及回滾段地址重構(gòu)出相應(yīng)的修改前的副本,并且用這些原值來還原當前數(shù)據(jù)文件中已修改但未提交的改變。如果有多個前映像,服務(wù)器進程會在一個前映像的頭部找到前前映像的回滾段地址,一直重構(gòu)出同一事務(wù)下的最早的一個前映像為止。一旦發(fā)出了COMMIT,用戶就不能ROLLBACK,這使得COMMIT后DBWN進程還沒有全部完成的后續(xù)動作得到了保障。下面我們要提到檢查點的作用,ckpt的觸發(fā),有以下幾種情況:1.當發(fā)生日志組切換的時候2.當滿足log_checkpoint_timeout、log_checkpoint_interval、fast_start_io_target、fast_start_mttr_target參數(shù)設(shè)置的時候3.當運行alter system switchlogfile的時候4.當運行alter systemckeckpoint的時候5.當運行alter tablespacetbs_name begin backupend backup的時候6.當運行alter tablespacedatafile offline的時候7.系統(tǒng)正常關(guān)閉時只有在4.7兩種情況下發(fā)生完全檢查點。發(fā)生完全檢查點時,首先系統(tǒng)記錄檢查點對應(yīng)的Checkpoint SCN,并記錄下該時刻修改的DB BUFFER對應(yīng)的日志文件的最新的重做字節(jié)地址(Redo Byte Address (RBA)),然后DBWN進程將這個重做字節(jié)地址(RBA)之前已發(fā)生的DB BUFFER中的臟緩沖寫入數(shù)據(jù)文件(之所以要以重做字節(jié)地址(RBA)為標志是因為在檢查點發(fā)生到檢查點完成之間的時間內(nèi),系統(tǒng)還在一直不斷的產(chǎn)生修改,這些修改所產(chǎn)生的DB BUFFER臟緩沖,以及日志條目將不會影響這次檢查點最后確認的一致性結(jié)果,也就是最后確認這個Checkpoint SCN之前的系統(tǒng)是一致的)。最后把Checkpoint SCN和RBA更新至控制文件,Checkpoint SCN更新至每個數(shù)據(jù)文件頭部,表明當前數(shù)據(jù)庫是一致的。日志切換并不導(dǎo)致一個完全檢點的發(fā)生,比如有三個日志文件組,當發(fā)生日志切換時發(fā)生檢查點,而發(fā)生日志切換一般是因為當前的LGWR正在寫重做日志,也就是LGWR當剛寫滿2號日志就立即觸發(fā)檢查點,于是系統(tǒng)開始核對3號日志中記錄的REDO項目所對應(yīng)的數(shù)據(jù)是否已經(jīng)從DB BUFFER中寫入數(shù)據(jù)文件(不管事務(wù)是否已提交),如果沒有寫入,檢查點就觸發(fā)DBWN進程將這些緩沖塊寫入數(shù)據(jù)文件,顯然LGWR因此而發(fā)生等待,除此以外,檢查點還讓DBWN進程將在2號日志中對應(yīng)修改的DB BUFFER塊寫入數(shù)據(jù)文件,然后繼續(xù)LGWR進程,直到LGWR進程將LGWR觸發(fā)之前存在于REDO LOG BUFFER中的所有緩沖(包含未提交的重做信息)寫入重做日志文件,檢查點再更新數(shù)據(jù)文件,控制文件頭部SCN。其實LGWR等待的并不是CKPT的完成,而是等待CKPT觸發(fā)的DBWN進程的完成??梢韵胂駭嚯姇r可能既有未COMMIT的事務(wù),也可能同時存在已COMMIT但DBWN未完成的情況,如果斷電時有一個已COMMIT但DBWN動作沒有完成的情況存在,因為已經(jīng)COMMIT,COMMIT會觸發(fā)LGWR進程,所以不管DBWN動作是否已完成,該語句將要影響的行及其產(chǎn)生的結(jié)果一定已經(jīng)記錄在重做日志文件中了,則實例重啟后,SMON進程從控制文件中記錄的上一次重做字節(jié)地址(RBA)開始,按照重做日志文件中的條目對數(shù)據(jù)文件和回滾段重新做一遍即前滾,注意這些條目的操作在斷電之前有的已經(jīng)被DBWN寫入了數(shù)據(jù)文件,有的還沒有來得及寫,不管有沒有寫進數(shù)據(jù)文件,前滾時都會再重新寫一次(9I之前是這樣的),9I之后,由于也在日志中記錄了DBWN改寫的塊信息,系統(tǒng)會過濾掉已寫入的條目而只重做那些未寫入的條目。對于一個未提交事務(wù),分幾種情況來描述:1)LGWR與DBWN一致的情況即一個語句執(zhí)行完成后很長時間也沒有COMMIT,這種情況一般不存在DBWN來不及完成的情況。只是沒有COMMIT而已。那么SMON將在前滾完成后,利用回滾段重構(gòu)出具有最小SCN的前映像,并把它的值寫回原位。2)事務(wù)執(zhí)行中斷電,即可能存在LGWR與DBWN不同步的情況(因為DBWN之前會觸發(fā)LGWR,所以DBWN對數(shù)據(jù)文件的修改一定會被先記錄在重做日志文件中。因此只可能存在已寫入重做日志而未來得及寫入數(shù)據(jù)文件的情況存在。而不可能存在已寫入數(shù)據(jù)文件卻沒有寫入日志文件的情況。),這種情況下SMON也會先前滾一點(即把數(shù)據(jù)文件與相應(yīng)的日志文件先同步再回滾,之所以說前滾一點,是指僅LGWR與DBWN之間進度的差距,而不是把這條語句進行到底再回滾,因為日志文件中記錄的是執(zhí)行語句操作的一個個塊的修改信息,而不只是記錄一條執(zhí)行語句的字面內(nèi)容),然后利用回滾段重構(gòu)出具有最小SCN的前映像,并把它的值寫回原位。由此可見,實例失敗后用于恢復(fù)的時間由兩個檢查點之間的間隔大小來決定,我們可以通個四個參數(shù)設(shè)置檢查點執(zhí)行的頻率,LOG_CHECKPOINT_IMTERVAL決定了兩個檢查點之間寫入重做日志文件的系統(tǒng)物理塊的大小,LOG_CHECKPOINT_TIMEOUT決定了兩個檢查點之間的時間長度,F(xiàn)AST_START_IO_TARGET決定了用于恢復(fù)時需要處理的塊的大小,F(xiàn)AST_START_MTTR_TARGET直接決定了用于恢復(fù)的時間的長短。檢查點的作用就是不斷的確認LGWR與DBWN之間的同步情況,以便實例失敗后從上一個檢查點開始恢復(fù),問題是兩個檢查點之間LGWR與DBWN大部分的操作是同步的,只是一小部分沒有同步,這種傳統(tǒng)的檢查點使實例恢復(fù)做了比較多的無用功,因此,ORACLE引入了增量檢查點,增量檢查點會在上一次傳統(tǒng)檢查點發(fā)生后到下一次傳統(tǒng)檢查點發(fā)生之前,不斷的更新記錄在控制文件中重做字節(jié)地址(RBA)(CKPT進程每三秒更新一次,見下面DBWN講述),這樣實例失敗后將直接從控制文件中記錄的最后更新的重做字節(jié)地址(RBA)開始進行前滾和回滾,這就省略掉了恢復(fù)時大部份的重做日志的重做(即使在9I以后的版本里也省略掉了大部分的過濾重做日志條目的時間)。(對以上描述做一個簡單的比喻:比如一個貿(mào)易公司下設(shè)經(jīng)營部、貨運部、監(jiān)督部,經(jīng)營部負責(zé)貿(mào)易合同的簽訂與記錄,貨運部負責(zé)按合同號的順序把貨物送達,監(jiān)督部負責(zé)定期檢查確認經(jīng)營部簽訂的合同與貨運部貨物送達情況之間的同步情況,監(jiān)督部每月檢查一次,每次檢查時,先確認當時正在裝車的貨物的合同號,并要求貨運部把在這個合同號之前的所有還存在臨時倉庫中的未送貨物全部送達。等貨運部完成監(jiān)督部下達的任務(wù)后,監(jiān)督部在檢查本上記錄下本次開始檢查時那票正在裝車的貨物的合同號,本次檢查完成。如果這個公司發(fā)生了一次人事大換血,公司重新開業(yè)后,監(jiān)督部就會從檢查本上記錄的合同號開始,檢查在這之后所有發(fā)生的合同及貨物送達情況,要求貨運部把所有客戶確認的但還未送達的貨物送達。把所有客戶未確認的貨物收回。監(jiān)督部發(fā)現(xiàn)這次重新開業(yè)后的工作量實在是太大了,幾乎核對了整整一個月的幾萬單合同(好在不是半年檢查一次_),為了防止今后出現(xiàn)這種情況,監(jiān)督部增加了一項工作內(nèi)容,每三天派人去記錄一下貨運部正在裝車的那票貨的合同號,今后如果發(fā)生類似情況,監(jiān)督部就從最后一次記錄的合同號開始核對,這樣工作量就小多了。)ORACLE的工作機制-4肖亞峰(xyf_tck)在這里我們要說一下回滾段存儲的數(shù)據(jù),假如是delete操作,則回滾段將會記錄整個行的數(shù)據(jù),假如是update,則回滾段只記錄行被修改了的字段的變化前的數(shù)據(jù)(前映像),也就是沒有被修改的字段是不會被記錄的,假如是insert,則回滾段只記錄插入記錄的rowid。這樣假如事務(wù)提交,那回滾段中簡單標記該事務(wù)已經(jīng)提交;假如是回退,則如果操作是delete,回退的時候把回滾段中數(shù)據(jù)重新寫回數(shù)據(jù)塊,操作如果是update,則把變化前數(shù)據(jù)修改回去,操作如果是insert,則根據(jù)記錄的rowid把該記錄刪除。注意,檢查點除了觸發(fā)LGWR和DBWN向數(shù)據(jù)塊頭部寫SCN和COMMIT SCN,檢查點還向控制文件和數(shù)據(jù)文件頭部寫SCN,而用戶的DML和COMMIT僅是向數(shù)據(jù)塊頭部寫SCN和COMMIT SCN而不更新控制文件和數(shù)據(jù)文件的SCN,SMON的前滾是以文件頭部的SCN為起始點的也就是從前一個檢查點開始,SMON的回滾是回滾所有回滾段中未標識為已提交的數(shù)據(jù)塊,用戶的回滾是回滾與此事務(wù)有關(guān)的回滾段中未標識為已提交的數(shù)據(jù)塊。下面我們要講DBWN如何來寫數(shù)據(jù)文件,在寫數(shù)據(jù)文件前首先要找到可寫的空閑數(shù)據(jù)塊,ORACLE中空閑數(shù)據(jù)塊可以通過FREELIST或BITMAP來維護,它們位于一個段的頭部用來標識當前段中哪些數(shù)據(jù)塊可以進行INSERT。在本地管理表空間中ORACLE自動管理分配給段的區(qū)的大小,只在本地管理的表空間中才能選用段自動管理,采用自動段空間管理的本地管理表空間中的段中的空閑數(shù)據(jù)塊的信息就存放在段中某些區(qū)的頭部,使用位圖來管理(最普通的情況是一個段的第一個區(qū)的第一個塊為FIRST LEVEL BITMAP BLOCK,第二個塊為SECOND LEVEL BITMAP BLOCK,第三個塊為PAGETABLE SEGMENT HEADER,再下面的塊為記錄數(shù)據(jù)的數(shù)據(jù)塊,F(xiàn)IRST LEVEL BITMAP BLOCK的父數(shù)據(jù)塊地址指向SECOND LEVEL BITMAP BLOCK,SECOND LEVEL BITMAP BLOCK的父數(shù)據(jù)塊地址指向PAGETABLE SEGMENT HEADER,F(xiàn)IRST LEVEL BITMAP BLOCK記錄了它所管理的所有塊(包括頭部三個塊,不僅僅指數(shù)據(jù)塊)的狀態(tài),標識的狀態(tài)有Metadata、75-100% free、50-75% free、25-50% free、0-25% free、full、unformatted,在SECOND LEVEL BITMAP BLOCK中有一個列表,記錄了它管理的FIRST LEVEL BITMAP BLOCK,PAGETABLE SEGMENT HEADER中記錄的內(nèi)容比較多,除了記錄了它管理的SECOND LEVEL BITMAP BLOCK,還記錄了各個區(qū)的首塊地址以及各個區(qū)的DB BLOCK的個數(shù),段的各個區(qū)所對應(yīng)的FIRST LEVEL BITMAP BLOCK的塊地址以及區(qū)里面記錄數(shù)據(jù)的數(shù)據(jù)塊的起始地址。如果一個區(qū)擁有很多塊,這時會在一個區(qū)里出現(xiàn)兩個或多個FIRST LEVEL BITMAP BLOCK,這些FIRST LEVEL BITMAP BLOCK分別管理一個區(qū)中的一些塊,當區(qū)的數(shù)據(jù)塊比較少時,一個區(qū)的FIRST LEVEL BITMAP BLOCK可以跨區(qū)管理多個區(qū)的數(shù)據(jù)塊,BITMAP BOLCK最多為三級)。采用手動管理的本地管理表空間中的段和數(shù)據(jù)字典管理的表空間中的段中的空閑數(shù)據(jù)塊的管理都使用位于段頭部的空閑列表來管理,例如SYSTEM表空間是本地管理表空間,但是它是采用了手動段空間管理,所以也是用FREELIST來管理段中的空閑數(shù)據(jù)塊的??臻e列表是一個邏輯上的鏈表,在段的HEADER BLOCK中記錄了一個指向第一個空閑塊的BLOCK ADDRESS,第一個DB BLOCK中同時也記錄了指向下一個空閑塊的BLOCK ADDRESS。以此形成一個單向鏈表。如果段上有兩個FREE LIST則會在段頭部的HEADER BLOCK存有兩個指針分別指向兩個空閑塊并建立獨立的兩個單向鏈表。空閑列表的工作方式:首先當建立一個段時,初始分配的第一個區(qū)的第一個塊會成為段的頭塊,初始分配的第一個區(qū)的其它塊將全部加入空閑列表,再次擴展一個區(qū)時,這個區(qū)中的塊立即全部加入空閑列表,擴展一次加入一次。與位圖管理不同的是用空閑列表時區(qū)的頭部將不記錄區(qū)里面空閑塊的信息。當其中空閑空間小于PCTFREE設(shè)置的值之后,這個塊從空閑列表刪除,即上一個指向它的塊中記錄的下一個空閑塊地址更改為其它空閑塊的地址,使得這個塊類似于被短路,當這個塊中的內(nèi)容降至PCTUSED設(shè)置的值之下后,這個數(shù)據(jù)塊被再次加入空閑列表,而且是加入到空閑列表前端,即頭塊直接指向它,它再指向原頭塊指向的空閑塊,位于空閑列表中的數(shù)據(jù)塊都是可以向其中INSERT的塊,但是INSERT都是從空閑列表指向的第一個塊開始插入,當一個塊移出了空閑列表,但只要其中還有保留空間就可以進行UPDATE,當對其中一行UPDATE一個大數(shù)據(jù)時,如果當前塊不能完全放下整個行,只會把整個行遷移到一個新的數(shù)據(jù)塊,并在原塊位置留下一個指向新塊的指針,這叫行遷移。如果一個數(shù)據(jù)塊可以INSERT,當插入一個當前塊裝不下的行時,這個行會溢出到兩個或兩個幾上的塊中,這叫行鏈接。如果用戶的動作是INSERT則服務(wù)器進程會先鎖定FREELIST,然后找到第一個空閑塊的地址,再釋放FREELIST,當多個服務(wù)器進程同時想要鎖定FREELIST時即發(fā)生FREELIST的爭用,也就是說多個進程只在同時INSERT時才會發(fā)生FREELIST爭用,可以在非采用自動段空間管理的表空間中創(chuàng)建表時指定FREELIST的個數(shù),默認為1,如果是在采用自動段空間管理的表空間中創(chuàng)建表,即使指定了FREELIST也會被忽略,因為此時將使用BITMAP而不是FREELIST來管理段中的空閑空間。采用自動段空間管理還會忽略的參數(shù)有PCTUSED和FREELIST GROUPS。如果用戶動作是UPDATE或DELETE等其它操作,服務(wù)器進程將不會使用到FREELIST和BITMAP,因為不要去尋找一個空閑塊,而使用鎖的隊列。對數(shù)據(jù)塊中數(shù)據(jù)操作必須使用transaction entries,即事務(wù)入口。在建立段時我們可以通過MINTRANS和MAXTRANS參數(shù)指定它的最大值和最小值,MAXTRANS規(guī)定了在段中每一個塊上最大并發(fā)事務(wù)數(shù)量,可以輸入1到255之間的值。我們可以把它比喻為是一些長在塊頭部的事務(wù)插座,每個插座后面是一個可以伸縮的操作手,當事務(wù)進程插到一個插座上時相當于找到一個可以操作數(shù)據(jù)塊中數(shù)據(jù)行的操作手,通過這個操作手,事務(wù)進程可以對塊中數(shù)據(jù)進行INSERT、UPDATE、DELETE等操作。在沒有超過MAXTRANS設(shè)定的最大值時,如果transaction entries不夠用,則會在塊上自動分配一個,但不會影響其它塊中的transaction entries數(shù)量。只不過INSERT操作必須要先找到空閑塊然后才能INSERT。那么DBWN是根據(jù)什么順序來寫DB BUFFER中的臟數(shù)據(jù)的呢?ORACLE從8I開始加入新的數(shù)據(jù)結(jié)構(gòu)-檢查點隊列(Buffer Checkpoint Queue)。檢查點隊列是一個鏈接隊列。這個隊列的按照Buffer塊第一次被修改的順序排列,分別指向被修改的Buffer塊。在DB_Buffer中的數(shù)據(jù)被第一次被修改時,會記錄所生成的REDO LOG條目的位置RBA作為該Buffer的Low RBA,記錄在該Buffer的頭部(Buffer Header),如果該數(shù)據(jù)繼續(xù)被修改,則把該塊修改的最新的REDO LOG的RBA作為High RBA記錄在該Buffer的頭部。如果DB_Buffer中的塊沒有被修改的數(shù)據(jù),則該塊的頭部不會有Low RBA和High RBA的信息。檢查點隊列按照被修改塊的Low RBA的遞增值鏈接修改塊,沒有被修改的塊因為沒有Low RBA,而不會加入到檢查點隊列中。在沒有檢查點發(fā)生時DBWR就按照檢查點隊列的Low RBA的升序,將被修改的塊寫入到數(shù)據(jù)文件中。當塊被寫入到數(shù)據(jù)文件后,該塊會從檢查點隊列中斷開。DBWR繼續(xù)寫下一個塊。CKPT進程每三秒記錄檢查點隊列中對應(yīng)的最小Low RBA到控制文件中,也就是更新控制文件中的CheckPointRBA,當實例崩潰時,恢復(fù)將從CheckPointRBA所指向的日志位置開始。這就是增量檢查點的行為和定義。CKPT進程也會記錄檢查點位置到數(shù)據(jù)文件的頭部,但是只是日志切換時才寫。而不是每三秒。當檢查點發(fā)生時,DBWN不會一直不停的寫DB BUFFER中臟數(shù)據(jù),它將寫到檢查點隊列的開始塊的Low RBA的值大于該檢查點的Checkpoint RBA的值時停止寫入,然后完成這次檢查點,CKPT進程將記錄該檢查點的有關(guān)信息到控制文件中去。 ORACLE的工作機制-5肖亞峰(xyf_tck)下面來講一下ORACLE鎖的機制,分鎖存器和鎖兩種。鎖存器是用來保護對內(nèi)存結(jié)構(gòu)的訪問,比如對DB BUFFER中塊的鎖存器申請,只有在DBWN完成后,這些DB BUFFER塊被解鎖。然后用于其它的申請。鎖存器不可以在進程間共享,鎖存器的申請要么成功要么失敗,沒有鎖存器申請隊列。主要的鎖存器有SHARED POOL鎖存器,LIBRARY CACHE鎖存器,CACHE BUFFERS LRU CHAIN鎖存器,CACHE BUFFERS CHAINS鎖存器,REDO ALLOCATION鎖存器,REDO COPY鎖存器。ORACLE的鎖是用來保護數(shù)據(jù)訪問的,鎖的限制比鎖存器要更寬松,比如,多個用戶在修改同一表的不同行時,可以共享一個表上的一個鎖,鎖的申請可以按照被申請的順序來排隊等候,然后依次應(yīng)用,這種排隊機制叫做隊列(ENPUEUE),如果兩個服務(wù)器進程試圖對同一表的同一行進行加鎖,則都進入鎖的申請隊列,先進的加鎖成功,后面的進程要等待,直到前一個進程解鎖才可以加鎖,這叫做鎖的爭用,而且一旦加鎖成功,這個鎖將一直保持到用戶發(fā)出COMMIT或ROOLBACK命令為止。如果兩個用戶鎖定各自的一行并請求對方鎖定的行的時候?qū)l(fā)生無限期等待即死鎖,死鎖的發(fā)生都是由于鎖的爭用而不是鎖存器的爭用引起的,ORACLE在遇到死鎖時,自動釋放其中一個用戶的鎖并回滾此用戶的改變。正常情況下發(fā)生鎖的爭用時,數(shù)據(jù)的最終保存結(jié)果由SCN來決定哪個進程的更改被最終保存。兩個用戶的服務(wù)器進程在申請同一表的多個行的鎖的時候是可以交錯進入鎖的申請隊列的。只有其中發(fā)生爭用才會進行等待。創(chuàng)建表時指定的MAXTRANS參數(shù)決定了表中的一個數(shù)據(jù)塊同時最多可以被幾個事務(wù)鎖定。下面來講一下ORACLE的讀一致性機制,ORACLE的讀一致性保證了事務(wù)之間的高度隔離性。下面是幾個關(guān)于回滾段讀一致性和死鎖的事例:有表:Test (id number(10) 有記錄1000000條SQL create table test (idnumber(10)tablespaceusers;表已創(chuàng)建。SQL begin2 foriin 1.1000000 loop3 insertinto test values(i);4 endloop;5 commit;6 end;7 /PL/SQL過程已成功完成一,大SELECT,小UPDATEA會話-Select * from test;-設(shè)scn=101-執(zhí)行時間09:10:11B會話-Update test set id=9999999 where id=1000000-設(shè)scn=102-執(zhí)行時間09:10:12我們會發(fā)現(xiàn)B會話會在A會話前完成,A會話中顯示的ID=100000是從回滾段中讀取的,因為A會話在讀到ID=1000000所在的BLOCK時發(fā)現(xiàn)BLOCK上有事務(wù)信息,因

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論