99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀SQL語句執(zhí)行過程詳解
SQL語句執(zhí)行過程詳解
2018-03-26
收藏
SQL語句執(zhí)行過程詳解
一條sql,plsql的執(zhí)行到底是怎樣執(zhí)行的呢?
一、SQL語句執(zhí)行原理:

第一步:客戶端把語句發(fā)給服務(wù)器端執(zhí)行

當(dāng)我們在客戶端執(zhí)行 select 語句時,客戶端會把這條 SQL 語句發(fā)送給服務(wù)器端,讓服務(wù)器端的
進(jìn)程來處理這語句。也就是說,Oracle 客戶端是不會做任何的操作,他的主要任務(wù)就是把客戶端產(chǎn)生
的一些 SQL 語句發(fā)送給服務(wù)器端。雖然在客戶端也有一個數(shù)據(jù)庫進(jìn)程,但是,這個進(jìn)程的作用跟服務(wù)器
上的進(jìn)程作用事不相同的。服務(wù)器上的數(shù)據(jù)庫進(jìn)程才會對SQL 語句進(jìn)行相關(guān)的處理。不過,有個問題需
要說明,就是客戶端的進(jìn)程跟服務(wù)器的進(jìn)程是一一對應(yīng)的。也就是說,在客戶端連接上服務(wù)器后,在客戶
端與服務(wù)器端都會形成一個進(jìn)程,客戶端上的我們叫做客戶端進(jìn)程;而服務(wù)器上的我們叫做服務(wù)器進(jìn)程。
第二步:語句解析
當(dāng)客戶端把 SQL 語句傳送到服務(wù)器后,服務(wù)器進(jìn)程會對該語句進(jìn)行解析。同理,這個解析的工作,
也是在服務(wù)器端所進(jìn)行的。雖然這只是一個解析的動作,但是,其會做很多“小動作”。
1. 查詢高速緩存(library cache)。服務(wù)器進(jìn)程在接到客戶端傳送過來的 SQL 語句時,不
會直接去數(shù)據(jù)庫查詢。而是會先在數(shù)據(jù)庫的高速緩存中去查找,是否存在相同語句的執(zhí)行計劃。如果在
數(shù)據(jù)高速緩存中,則服務(wù)器進(jìn)程就會直接執(zhí)行這個 SQL 語句,省去后續(xù)的工作。所以,采用高速數(shù)據(jù)緩
存的話,可以提高 SQL 語句的查詢效率。一方面是從內(nèi)存中讀取數(shù)據(jù)要比從硬盤中的數(shù)據(jù)文件中讀取
數(shù)據(jù)效率要高,另一方面,也是因為這個語句解析的原因。
不過這里要注意一點,這個數(shù)據(jù)緩存跟有些客戶端軟件的數(shù)據(jù)緩存是兩碼事。有些客戶端軟件為了
提高查詢效率,會在應(yīng)用軟件的客戶端設(shè)置數(shù)據(jù)緩存。由于這些數(shù)據(jù)緩存的存在,可以提高客戶端應(yīng)用軟
件的查詢效率。但是,若其他人在服務(wù)器進(jìn)行了相關(guān)的修改,由于應(yīng)用軟件數(shù)據(jù)緩存的存在,導(dǎo)致修改的
數(shù)據(jù)不能及時反映到客戶端上。從這也可以看出,應(yīng)用軟件的數(shù)據(jù)緩存跟數(shù)據(jù)庫服務(wù)器的高速數(shù)據(jù)緩存
不是一碼事。
2. 語句合法性檢查(data dict cache)。當(dāng)在高速緩存中找不到對應(yīng)的 SQL 語句時,則服
務(wù)器進(jìn)程就會開始檢查這條語句的合法性。這里主要是對 SQL 語句的語法進(jìn)行檢查,看看其是否合乎
語法規(guī)則。如果服務(wù)器進(jìn)程認(rèn)為這條 SQL 語句不符合語法規(guī)則的時候,就會把這個錯誤信息,反饋給客
戶端。在這個語法檢查的過程中,不會對 SQL 語句中所包含的表名、列名等等進(jìn)行 SQL 他只是語法
上的檢查。
3. 語言含義檢查(data dict cache)。若 SQL 語句符合語法上的定義的話,則服務(wù)器進(jìn)程
接下去會對語句中的字段、表等內(nèi)容進(jìn)行檢查??纯催@些字段、表是否在數(shù)據(jù)庫中。如果表名與列名不
準(zhǔn)確的話,則數(shù)據(jù)庫會就會反饋錯誤信息給客戶端。所以,有時候我們寫 select 語句的時候,若語法
與表名或者列名同時寫錯的話,則系統(tǒng)是先提示說語法錯誤,等到語法完全正確后,再提示說列名或表名
錯誤。
4. 獲得對象解析鎖(control structer)。當(dāng)語法、語義都正確后,系統(tǒng)就會對我們需要查詢
的對象加鎖。這主要是為了保障數(shù)據(jù)的一致性,防止我們在查詢的過程中,其他用戶對這個對象的結(jié)構(gòu)發(fā)
生改變。
5. 數(shù)據(jù)訪問權(quán)限的核對(data dict cache)。當(dāng)語法、語義通過檢查之后,客戶端還不一定
能夠取得數(shù)據(jù)。服務(wù)器進(jìn)程還會檢查,你所連接的用戶是否有這個數(shù)據(jù)訪問的權(quán)限。若你連接上服務(wù)器
的用戶不具有數(shù)據(jù)訪問權(quán)限的話,則客戶端就不能夠取得這些數(shù)據(jù)。有時候我們查詢數(shù)據(jù)的時候,辛辛苦
苦地把 SQL 語句寫好、編譯通過,但是,最后系統(tǒng)返回個 “沒有權(quán)限訪問數(shù)據(jù)”的錯誤信息,讓我們氣
半死。這在前端應(yīng)用軟件開發(fā)調(diào)試的過程中,可能會碰到。所以,要注意這個問題,數(shù)據(jù)庫服務(wù)器進(jìn)程先
檢查語法與語義,然后才會檢查訪問權(quán)限。
6. 確定最佳執(zhí)行計劃 ?。當(dāng)語句與語法都沒有問題,權(quán)限也匹配的話,服務(wù)器進(jìn)程還是不會直接對
數(shù)據(jù)庫文件進(jìn)行查詢。服務(wù)器進(jìn)程會根據(jù)一定的規(guī)則,對這條語句進(jìn)行優(yōu)化。不過要注意,這個優(yōu)化是有
限的。一般在應(yīng)用軟件開發(fā)的過程中,需要對數(shù)據(jù)庫的 sql 語言進(jìn)行優(yōu)化,這個優(yōu)化的作用要大大地大
于服務(wù)器進(jìn)程的自我優(yōu)化。所以,一般在應(yīng)用軟件開發(fā)的時候,數(shù)據(jù)庫的優(yōu)化是少不了的。當(dāng)服務(wù)器進(jìn)程
的優(yōu)化器確定這條查詢語句的最佳執(zhí)行計劃后,就會將這條 SQL 語句與執(zhí)行計劃保存到數(shù)據(jù)高速緩存
(library cache)。如此的話,等以后還有這個查詢時,就會省略以上的語法、語義與權(quán)限檢查的步驟,
而直接執(zhí)行 SQL 語句,提高 SQL 語句處理效率。
第三步:語句執(zhí)行
語句解析只是對 SQL 語句的語法進(jìn)行解析,以確保服務(wù)器能夠知道這條語句到底表達(dá)的是什么意
思。等到語句解析完成之后,數(shù)據(jù)庫服務(wù)器進(jìn)程才會真正的執(zhí)行這條 SQL 語句。這個語句執(zhí)行也分兩
種情況。
一是若被選擇行所在的數(shù)據(jù)塊已經(jīng)被讀取到數(shù)據(jù)緩沖區(qū)的話,則服務(wù)器進(jìn)程會直接把這個數(shù)據(jù)傳遞
給客戶端,而不是從數(shù)據(jù)庫文件中去查詢數(shù)據(jù)。
若數(shù)據(jù)不在緩沖區(qū)中,則服務(wù)器進(jìn)程將從數(shù)據(jù)庫文件中查詢相關(guān)數(shù)據(jù),并把這些數(shù)據(jù)放入到數(shù)據(jù)緩沖
區(qū)中(buffer cache)。
第四步:提取數(shù)據(jù)
當(dāng)語句執(zhí)行完成之后,查詢到的數(shù)據(jù)還是在服務(wù)器進(jìn)程中,還沒有被傳送到客戶端的用戶進(jìn)程。所以,
在服務(wù)器端的進(jìn)程中,有一個專門負(fù)責(zé)數(shù)據(jù)提取的一段代碼。他的作用就是把查詢到的數(shù)據(jù)結(jié)果返回給
用戶端進(jìn)程,從而完成整個查詢動作。從這整個查詢處理過程中,我們在數(shù)據(jù)庫開發(fā)或者應(yīng)用軟件開發(fā)過
程中,需要注意以下幾點:
一是要了解數(shù)據(jù)庫緩存跟應(yīng)用軟件緩存是兩碼事情。數(shù)據(jù)庫緩存只有在數(shù)據(jù)庫服務(wù)器端才存在,在
客戶端是不存在的。只有如此,才能夠保證數(shù)據(jù)庫緩存中的內(nèi)容跟數(shù)據(jù)庫文件的內(nèi)容一致。才能夠根據(jù)
相關(guān)的規(guī)則,防止數(shù)據(jù)臟讀、錯讀的發(fā)生。而應(yīng)用軟件所涉及的數(shù)據(jù)緩存,由于跟數(shù)據(jù)庫緩存不是一碼事
情,所以,應(yīng)用軟件的數(shù)據(jù)緩存雖然可以提高數(shù)據(jù)的查詢效率,但是,卻打破了數(shù)據(jù)一致性的要求,有時候
會發(fā)生臟讀、錯讀等情況的發(fā)生。所以,有時候,在應(yīng)用軟件上有專門一個功能,用來在必要的時候清除
數(shù)據(jù)緩存。不過,這個數(shù)據(jù)緩存的清除,也只是清除本機(jī)上的數(shù)據(jù)緩存,或者說,只是清除這個應(yīng)用程序
的數(shù)據(jù)緩存,而不會清除數(shù)據(jù)庫的數(shù)據(jù)緩存。
二是絕大部分 SQL 語句都是按照這個處理過程處理的。我們 DBA 或者基于 Oracle 數(shù)據(jù)庫的
開發(fā)人員了解這些語句的處理過程,對于我們進(jìn)行涉及到 SQL 語句的開發(fā)與調(diào)試,是非常有幫助的。有
時候,掌握這些處理原則,可以減少我們排錯的時間。特別要注意,數(shù)據(jù)庫是把數(shù)據(jù)查詢權(quán)限的審查放在
語法語義的后面進(jìn)行檢查的。所以,有時會若光用數(shù)據(jù)庫的權(quán)限控制原則,可能還不能滿足應(yīng)用軟件權(quán)限
控制的需要。此時,就需要應(yīng)用軟件的前臺設(shè)置,實現(xiàn)權(quán)限管理的要求。而且,有時應(yīng)用數(shù)據(jù)庫的權(quán)限管
理,也有點顯得繁瑣,會增加服務(wù)器處理的工作量。因此,對于記錄、字段等的查詢權(quán)限控制,大部分程
序涉及人員喜歡在應(yīng)用程序中實現(xiàn),而不是在數(shù)據(jù)庫上實現(xiàn)。
DBCC DROPCLEANBUFFERS
從緩沖池中刪除所有清除緩沖區(qū)。
DBCC FREEPROCCACHE
從過程緩存中刪除所有元素。
DBCC FREESYSTEMCACHE
從所有緩存中釋放所有未使用的緩存條目
SQL語句中的函數(shù)、關(guān)鍵字、排序等執(zhí)行順序:
1. FROM 子句返回初始結(jié)果集。
2. WHERE 子句排除不滿足搜索條件的行。
3. GROUP BY 子句將選定的行收集到 GROUP BY 子句中各個唯一值的組中。
4. 選擇列表中指定的聚合函數(shù)可以計算各組的匯總值。
5. 此外,HAVING 子句排除不滿足搜索條件的行。
6. 計算所有的表達(dá)式;
7. 使用 order by 對結(jié)果集進(jìn)行排序。
8. 查找你要搜索的字段。
二、SQL語句執(zhí)行完整過程:
1.用戶進(jìn)程提交一個 sql 語句:
update temp set a=a*2,給服務(wù)器進(jìn)程。
2.服務(wù)器進(jìn)程從用戶進(jìn)程把信息接收到后,在 PGA 中就要此進(jìn)程分配所需內(nèi)存,存儲相關(guān)的信息,如在會
話內(nèi)存存儲相關(guān)的登錄信息等。
3.服務(wù)器進(jìn)程把這個 sql 語句的字符轉(zhuǎn)化為 ASCII 等效數(shù)字碼,接著這個 ASCII 碼被傳遞給一個
HASH 函數(shù),并返回一個 hash 值,然后服務(wù)器進(jìn)程將到shared pool 中的 library cache 中去查找是否存在相
同的 hash 值,如果存在,服務(wù)器進(jìn)程將使用這條語句已高速緩存在 SHARED POOL 的library cache 中的已
分析過的版本來執(zhí)行。
4.如果不存在,服務(wù)器進(jìn)程將在 CGA 中,配合 UGA 內(nèi)容對 sql,進(jìn)行語法分析,首先檢查語法的正確性,接
著對語句中涉及的表,索引,視圖等對象進(jìn)行解析,并對照數(shù)據(jù)字典檢查這些對象的名稱以及相關(guān)結(jié)構(gòu),并根據(jù)
ORACLE 選用的優(yōu)化模式以及數(shù)據(jù)字典中是否存在相應(yīng)對象的統(tǒng)計數(shù)據(jù)和是否使用了存儲大綱來生成一個
執(zhí)行計劃或從存儲大綱中選用一個執(zhí)行計劃,然后再用數(shù)據(jù)字典核對此用戶對相應(yīng)對象的執(zhí)行權(quán)限,最后生成
一個編譯代碼。
5.ORACLE 將這條 sql 語句的本身實際文本、HASH 值、編譯代碼、與此語名相關(guān)聯(lián)的任何統(tǒng)計數(shù)據(jù)
和該語句的執(zhí)行計劃緩存在 SHARED POOL 的 library cache中。服務(wù)器進(jìn)程通過 SHARED POOL 鎖存
器(shared pool latch)來申請可以向哪些共享 PL/SQL 區(qū)中緩存這此內(nèi)容,也就是說被SHARED POOL 鎖存
器鎖定的 PL/SQL 區(qū)中的塊不可被覆蓋,因為這些塊可能被其它進(jìn)程所使用。
6.在 SQL 分析階段將用到 LIBRARY
 CACHE,從數(shù)據(jù)字典中核對表、視圖等結(jié)構(gòu)的時候,需要將數(shù)據(jù)
字典從磁盤讀入 LIBRARY
 CACHE,因此,在讀入之前也要使用LIBRARY
 CACHE 鎖存器(library cache
pin,library cache lock)來申請用于緩存數(shù)據(jù)字典。 到現(xiàn)在為止,這個 sql 語句已經(jīng)被編譯成可執(zhí)行的代碼了,
但還不知道要操作哪些數(shù)據(jù),所以服務(wù)器進(jìn)程還要為這個 sql 準(zhǔn)備預(yù)處理數(shù)據(jù)。
7.首先服務(wù)器進(jìn)程要判斷所需數(shù)據(jù)是否在 db buffer 存在,如果存在且可用,則直接獲取該數(shù)據(jù),同時根據(jù)
LRU 算法增加其訪問計數(shù);如果 buffer 不存在所需數(shù)據(jù),則要從數(shù)據(jù)文件上讀取首先服務(wù)器進(jìn)程將在表頭部
請求 TM 鎖(保證此事務(wù)執(zhí)行過程其他用戶不能修改表的結(jié)構(gòu)),如果成功加 TM 鎖,再請求一些行級鎖(TX
鎖),如果 TM、TX 鎖都成功加鎖,那么才開始從數(shù)據(jù)文件讀數(shù)據(jù),在讀數(shù)據(jù)之前,要先為讀取的文件準(zhǔn)備好
buffer 空間。服務(wù)器進(jìn)程需要掃面 LRU list 尋找 free db buffer,掃描的過程中,服務(wù)器進(jìn)程會把發(fā)現(xiàn)的所有
已經(jīng)被修改過的 db buffer 注冊到 dirty list 中, 這些 dirty buffer 會通過 dbwr 的觸發(fā)條件,隨后會被寫出到
數(shù)據(jù)文件,找到了足夠的空閑 buffer,就可以把請求的數(shù)據(jù)行所在的數(shù)據(jù)塊放入到 db buffer 的空閑區(qū)域或者
覆蓋已經(jīng)被擠出 LRU list 的非臟數(shù)據(jù)塊緩沖區(qū),并排列在 LRU list 的頭部,也就是在數(shù)據(jù)塊放入 DB
BUFFER 之前也是要先申請 db buffer 中的鎖存器,成功加鎖后,才能讀數(shù)據(jù)到 db buffer。
8.記日志 現(xiàn)在數(shù)據(jù)已經(jīng)被讀入到 db buffer 了,現(xiàn)在服務(wù)器進(jìn)程將該語句所影響的并被讀
入 db buffer 中的這些行數(shù)據(jù)的 rowid 及要更新的原值和新值及 scn 等信息從 PGA 逐條的寫入 redo log
buffer 中。在寫入 redo log buffer 之前也要事先請求 redo log buffer 的鎖存器,成功加鎖后才開始寫入,當(dāng)
寫入達(dá)到 redo log buffer 大小的三分之一或?qū)懭肓窟_(dá)到 1M 或超過三秒后或發(fā)生檢查點時或者 dbwr 之前
發(fā)生,都會觸發(fā) lgwr 進(jìn)程把 redo log buffer 的數(shù)據(jù)寫入磁盤上的 redo file 文件中(這個時候會產(chǎn)生log file
sync 等待事件)
已經(jīng)被寫入 redofile 的 redo log buffer 所持有的鎖存器會被釋放,并可被后來的寫入信息覆蓋,
redo log buffer是循環(huán)使用的。Redo file 也是循環(huán)使用的,當(dāng)一個 redo file 寫滿后,lgwr 進(jìn)程會自動切換到
下一 redo file(這個時候可能出現(xiàn) log fileswitch(checkpoint complete)等待事件)。如果是歸檔模式,歸檔進(jìn)
程還要將前一個寫滿的 redo file 文件的內(nèi)容寫到歸檔日志文件中(這個時候可能出現(xiàn) log file
switch(archiving needed)。
9.為事務(wù)建立回滾段 在完成本事務(wù)所有相關(guān)的 redo log buffer 之后,服務(wù)器進(jìn)程開始改寫這個 db buffer
的塊頭部事務(wù)列表并寫入 scn,然后 copy 包含這個塊的頭部事務(wù)列表及 scn 信息的數(shù)據(jù)副本放入回滾段中,將
這時回滾段中的信息稱為數(shù)據(jù)塊的“前映像“,這個”前映像“用于以后的回滾、恢復(fù)和一致性讀。(回滾段可以
存儲在專門的回滾表空間中,這個表空間由一個或多個物理文件組成,并專用于回滾表空間,回滾段也可在其它
表空間中的數(shù)據(jù)文件中開辟。
10.本事務(wù)修改數(shù)據(jù)塊 準(zhǔn)備工作都已經(jīng)做好了,現(xiàn)在可以改寫 db buffer 塊的數(shù)據(jù)內(nèi)容了,并在塊的頭部寫
入回滾段的地址。
11.放入 dirty list 如果一個行數(shù)據(jù)多次 update 而未 commit,則在回滾段中將會有多個“前映像“,除了第
一個”前映像“含有 scn 信息外,其他每個“前映像“的頭部都有 scn 信息和“前前映像”回滾段地址。一個
update 只對應(yīng)一個 scn,然后服務(wù)器進(jìn)程將在 dirty list 中建立一
條指向此 db buffer 塊的指針(方便 dbwr 進(jìn)程可以找到 dirty list 的 db buffer 數(shù)據(jù)塊并寫入數(shù)據(jù)文件中)。
接著服務(wù)器進(jìn)程會從數(shù)據(jù)文件中繼續(xù)讀入第二個數(shù)據(jù)塊,重復(fù)前一數(shù)據(jù)塊的動作,數(shù)據(jù)塊的讀入、記日志、建
立回滾段、修改數(shù)據(jù)塊、放入 dirty list。當(dāng) dirty queue 的長度達(dá)到閥值(一般是 25%),服務(wù)器進(jìn)程將通知
dbwr 把臟數(shù)據(jù)寫出,就是釋放 db buffer 上的鎖存器,騰出更多的 free db buffer。前面一直都是在說明
oracle 一次讀一個數(shù)據(jù)塊,其實 oracle 可以一次讀入多個數(shù)據(jù)塊(db_file_multiblock_read_count 來設(shè)置一
次讀入塊的個數(shù))
說明:
在預(yù)處理的數(shù)據(jù)已經(jīng)緩存在 db buffer 或剛剛被從數(shù)據(jù)文件讀入到 db buffer 中,就要根據(jù) sql 語句
的類型來決定接下來如何操作。
1>如果是 select 語句,則要查看 db buffer 塊的頭部是否有事務(wù),如果有事務(wù),則從回滾段中讀取數(shù)據(jù);如
果沒有事務(wù),則比較 select 的 scn 和 db buffer 塊頭部的 scn,如果前者小于后者,仍然要從回滾段中讀取數(shù)據(jù);
如果前者大于后者,說明這是一非臟緩存,可以直接讀取這個 db buffer 塊的中內(nèi)容。
2>如果是 DML 操作,則即使在 db buffer 中找到一個沒有事務(wù),而且 SCN 比自己小的非臟
緩存數(shù)據(jù)塊,服務(wù)器進(jìn)程仍然要到表的頭部對這條記錄申請加鎖,加鎖成功才能進(jìn)行后續(xù)動作,如果不成功,則要
等待前面的進(jìn)程解鎖后才能進(jìn)行動作(這個時候阻塞是 tx 鎖阻塞)。
用戶 commit 或 rollback 到現(xiàn)在為止,數(shù)據(jù)已經(jīng)在 db buffer 或數(shù)據(jù)文件中修改完
成,但是否要永久寫到數(shù)文件中,要由用戶來決定 commit(保存更改到數(shù)據(jù)文件) rollback 撤銷數(shù)據(jù)的更改)。
1.用戶執(zhí)行 commit 命令
只有當(dāng) sql 語句所影響的所有行所在的最后一個塊被讀入 db buffer 并且重做信息被寫入 redo log
buffer(僅指日志緩沖區(qū),而不包括日志文件)之后,用戶才可以發(fā)去 commit 命令,commit 觸發(fā) lgwr 進(jìn)程,但不
強(qiáng)制立即 dbwr來釋放所有相應(yīng) db buffer 塊的鎖(也就是no-force-at-commit,即提交不強(qiáng)制寫),也就是說有
可能雖然已經(jīng) commit 了,但在隨后的一段時間內(nèi) dbwr 還在寫這條 sql 語句所涉及的數(shù)據(jù)塊。表頭部的行鎖
并不在 commit 之后立即釋放,而是要等 dbwr 進(jìn)程完成之后才釋放,這就可能會出現(xiàn)一個用戶請求另一用戶
已經(jīng) commit 的資源不成功的現(xiàn)象。
A .從 Commit 和 dbwr 進(jìn)程結(jié)束之間的時間很短,如果恰巧在 commit 之后,dbwr 未結(jié)束之前斷電,因為
commit 之后的數(shù)據(jù)已經(jīng)屬于數(shù)據(jù)文件的內(nèi)容,但這部分文件沒有完全寫入到數(shù)據(jù)文件中。所以需要前滾。由
于 commit 已經(jīng)觸發(fā) lgwr,這些所有未來得及寫入數(shù)據(jù)文件的更改會在實例重啟后,由 smon 進(jìn)程根據(jù)重做日
志文件來前滾,完成之前 commit 未完成的工作(即把更改寫入數(shù)據(jù)文件)。
B.如果未 commit 就斷電了,因為數(shù)據(jù)已經(jīng)在 db buffer 更改了,沒有 commit,說明這部分?jǐn)?shù)據(jù)不屬于數(shù)
據(jù)文件,由于 dbwr 之前觸發(fā) lgwr 也就是只要數(shù)據(jù)更改,(肯定要先有 log) 所有 DBWR,在數(shù)據(jù)文件上的修改
都會被先一步記入重做日志文件,實例重啟后,SMON 進(jìn)程再根據(jù)重做日志文件來回滾。
其實 smon 的前滾回滾是根據(jù)檢查點來完成的,當(dāng)一個全部檢查點發(fā)生的時候,首先讓 LGWR 進(jìn)程將
redo log buffer 中的所有緩沖(包含未提交的重做信息)寫入重做日志文件,然后讓 dbwr 進(jìn)程將 db buffer 已
提交的緩沖寫入數(shù)據(jù)文件(不強(qiáng)制寫未提交的)。然后更新控制文件和數(shù)據(jù)文件頭部的 SCN,表明當(dāng)前數(shù)據(jù)庫
是一致的,在相鄰的兩個檢查點之間有很多事務(wù),有提交和未提交的。
像前面的前滾回滾比較完整的說法是如下的說明:

A.發(fā)生檢查點之前斷電,并且當(dāng)時有一個未提交的改變正在進(jìn)行,實例重啟之后,SMON 進(jìn)程將從上一個
檢查點開始核對這個檢查點之后記錄在重做日志文件中已提交的和未提交改變,因為
dbwr 之前會觸發(fā) lgwr,所以 dbwr 對數(shù)據(jù)文件的修改一定會被先記錄在重做日志文件中。因此,斷電前被
DBWN 寫進(jìn)數(shù)據(jù)文件的改變將通過重做日志文件中的記錄進(jìn)行還原,叫做回滾,
B. 如果斷電時有一個已提交,但 dbwr 動作還沒有完全完成的改變存在,因為已經(jīng)提交,提交會觸發(fā) lgwr
進(jìn)程,所以不管 dbwr 動作是否已完成,該語句將要影響的行及其產(chǎn)生的結(jié)果一定已經(jīng)記錄在重做日志文件中
了,則實例重啟后,SMON 進(jìn)程根據(jù)重做日志文件進(jìn)行前滾.
實例失敗后用于恢復(fù)的時間由兩個檢查點之間的間隔大小來決定,可以通個四個參數(shù)設(shè)置檢查點執(zhí)行的頻
率:

Log_checkpoint_interval:
決定兩個檢查點之間寫入重做日志文件的系統(tǒng)物理塊(redo blocks)
的大小,默認(rèn)值是 0,無限制。
log_checkpoint_timeout:
 兩 個 檢 查 點 之 間 的 時 間 長 度(秒)默 認(rèn) 值 1800s。
fast_start_io_target:
決定了用于恢復(fù)時需要處理的塊的多少,默認(rèn)值是 0,無限制。
fast_start_mttr_target:
直接決定了用于恢復(fù)的時間的長短,默認(rèn)值是 0,無限制(SMON 進(jìn)程執(zhí)行的前滾
和回滾與用戶的回滾是不同的,SMON 是根據(jù)重做日志文件進(jìn)行前滾或回滾,而用戶的回滾一定是根據(jù)回滾段
的內(nèi)容進(jìn)行回滾的。
在這里要說一下回滾段存儲的數(shù)據(jù),假如是 delete 操作,則回滾段將會記錄整個行的數(shù)據(jù),假如是 update,
則回滾段只記錄被修改了的字段的變化前的數(shù)據(jù)(前映像),也就是沒有被修改的字段是不會被記錄的,假如是
insert,則回滾段只記錄插入記錄的 rowid。 這樣假如事務(wù)提交,那回滾段中簡單標(biāo)記該事務(wù)已經(jīng)提交;假如是
回退,則如果操作是 delete,回退的時候把回滾段中數(shù)據(jù)重新寫回數(shù)據(jù)塊,操作如果是 update,則把變化前數(shù)據(jù)
修改回去,操作如果是 insert,則根據(jù)記錄的 rowid 把該記錄刪除。
2.如果用戶 rollback。
則服務(wù)器進(jìn)程會根據(jù)數(shù)據(jù)文件塊和 DB BUFFER 中塊的頭部的事務(wù)列表和 SCN 以及回滾段地址找到
回滾段中相應(yīng)的修改前的副本,并且用這些原值來還原當(dāng)前數(shù)據(jù)文件中已修改但未提交的改變。如果有多個
“前映像”,服務(wù)器進(jìn)程會在一個“前映像”的頭部找到“前前映像”的回滾段地址,一直找到同一事務(wù)下的最早的
一個“前映像”為止。一旦發(fā)出了 COMMIT,用戶就不能rollback,這使得 COMMIT 后 DBWR 進(jìn)程還沒有
全部完成的后續(xù)動作得到了保障。到現(xiàn)在為例一個事務(wù)已經(jīng)結(jié)束了。
說明:
 TM 鎖:
符合 lock 機(jī)制的,用于保護(hù)對象的定義不被修改。 TX 鎖:
這個鎖代表一個事務(wù),是行
級鎖,用數(shù)據(jù)塊頭、數(shù)據(jù)記錄頭的一些字段表示,也是符合 lock 機(jī)制,有 resource structure、lock
structure、enqueue 算法。

數(shù)據(jù)分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個參數(shù)驗證碼對象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺檢測極驗服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時表示是新驗證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計時完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }