由SQL語句執行過程觸發對Oracle體系結構的思考

dbhelper發表於2014-11-27

 

1.首先開啟遊標(記憶體指標),

2.語法檢查:來了一條update語句首先你要看這條語句是不是SQL語句也就是先對他進行語法分析,語法分析是在share pool的庫快取去中,並在此儲存起來,

3.語義檢查:語法沒問題後,要檢驗它所涉及的表、索引、以及許可權等資料庫物件及相關屬性是否正確 ,也就是語義檢查,是在share pool 的資料字典快取區中進行,

4.查harsh值,這個過程是在share pool的庫快取區進行的,如果有相同的執行計劃存在,則直接呼叫即可這樣就是軟解析,否則還要進行硬解析,也就是新生成執行計劃,硬解析很消耗資源。

5,有了執行計劃後,就該著執行了。

6.處理結果。

7.關閉遊標

看似簡單的流程裡面  有很多值得思考的地方。

1)如果是select 語句 ,伺服器程式首先會在database buffer cache 中檢視是否有要查詢的資料塊,如果有則直接在快取區中查到結果並返回給使用者,如果沒有,伺服器程式會從底層資料檔案中把要查詢的資料所在的塊複製到資料庫快取記憶體區快取中,然後再按上述步驟進行查詢並返回結果。

2)還涉及到如果快取區中沒有可用的空間了(資料庫快取區中的資料塊有四種狀態,1髒快—就是被修改過且與底層資料檔案的塊不一致,也沒有被重新整理到資料檔案的塊,2.乾淨塊—也是被修改過的塊,但是已經被重新整理到了資料檔案中,此塊是可以被使用的,再來了直接覆寫就可以了,3.free 塊 —這是還沒有被使用過的,當然可以被使用了4.pin塊就是正在被使用的塊,上面有鎖。不能被使用。),這是你就不能把想要查詢的資料塊複製到快取區,只能等待。。這種情況就會觸發DBWn程式去寫快取區中的髒塊,以便騰出塊來用。

3)那麼還有什麼會觸發DBWn程式寫呢,主要有這幾種1.快取區中的髒快已經達到極限值(1/4滿)2.遇到檢查點時,3.設定表空間離線(暫時不受資料庫管理控制)這是因為既然你都不讓資料庫控制了,那你得保證在離線時,快取區中沒有與資料檔案不一致的塊,有的話你就得重新整理出來。3.熱備份開始的時候。可以這樣理解:備份目的就是以便恢復,那你肯定是想要備份一份一致性的資料,如果快取區中有不一樣的,肯定會重新整理出來。

4)那又有問題了,既然1/4滿時,就會觸發dbwn寫程式,那麼還提資料庫快取區快取記憶體滿的情況幹什麼啊,它還能滿? 原因是這樣的雖然你在1/4滿時已經開始重新整理髒快,但是同時也會有新的髒快在產生,寫髒快的速度不一定比產生的速度快。。。

5)上面還提到了遇到檢查點也會觸發DBWn程式,那什麼是檢查點呢?這就涉及到了另一個後臺程式CKPT(檢查點程式)它的作用:1.給DBWn程式訊號,觸發它去重新整理髒快,2.看dbwn 寫了多少髒快了 並把此資訊記錄到控制檔案,更新資料檔案頭scn號,更新控制檔案的scn 號,發一次檢查點,就會使資料庫到達一致性狀態(就是資料檔案頭的scn,控制檔案中記錄資料檔案的頭的scn,以及控制檔案有個總的scn,這三個scn號一樣)應該注意的是真正建立檢查點的主要是DBWn程式,CKPT只是更新資料檔案的檔案頭,以輔助真正建立檢查點的的程式(DBWn)——167程式設計藝術

5)那麼什麼是scn—系統變更號   其實你可以把它理解為就是記錄資料庫變化的一個時鐘,它是不斷增長不能減少的(就像你不能回到過去一樣),而且是不能被命令給修改的(bbed是另一種情況),scn號用於保證資料庫的讀一致性和檢查點,每次commit 都會加1.

6)上面說了select 語句的一些事情,那麼update語句呢,首先伺服器程式也會看快取區中有沒有要修改的塊,然後處理過程和select 類似,假如已經修改了塊兒,但是還沒有commit,這會面臨一些問題,首先,你用修改這個塊的使用者查它是修改後的值,這時候如果你用另一個使用者查詢這個塊,它返回的是修改之前的資料,例如你把x=10改成了x=100,但是沒有提交,你去查詢時,它返回x=10,那他是怎麼實現的呢,其實是在改之前會把當時的值放在under表空間中(這個過程是伺服器程式完成的)——以便於你回滾,因為Oracle會保證一致性讀,所以會讀取修改前的值,因為有鎖,另一個使用者是無法使用這個塊的,所以他會重新複製塊到快取區。Commit之後無論是誰查都是修改後的值了。(一定注意此時快取區的髒快不一定被重新整理出來了,因為commit 不會觸發DBWn程式重新整理髒塊,這一點好多人誤解

7)既然commit之前與之後差距這麼大,那commit  到底做了什麼呢?311(摘自程式設計藝術)

COMMIT是一個非常快的操作,當我們釋出commit命令時,真正困難的動作已經完成,在中已經執行了資料更改,所以已經完成了99%的任務。

例如:下列操作已經產生: 

 1. 在SGA(Buffer Cache)中已經生成了undo塊;

 2.在SGA(Buffer Cache)中已經生成了產生改變的資料塊和索引塊;

 3.在REDO LOG BUFFER生成了前面兩項的redo資訊;

 4.buffer中的資料可能已經有一部分輸出到了磁碟;(依賴於前三項產生的資料量大小以及操作需要的時間)   

 5.所有需要的鎖已經獲得;     

 當執行COMMIT命令時,只執行如下操作:     

 1.為事務生成SCN:SCN是ORACLE資料庫的一種計時資訊,用以保證事務的順序性,

同時還用於失敗恢復和保證資料庫的讀一致性和檢查點,無論何時何人提交,SCN自動加1

 2.將事務相關的未寫入redo log file中的redo資訊從redo log buffer寫入到redo log file,這才是真實的COMMIT,這步操作完成,說明我們已經完成COMMIT,事務從V$TRANSACTION中移除;

 3.V$LOCK中記錄的SESSION關於該事務鎖,這些鎖會被釋放,其他需要這些鎖的事務被喚醒;

 4.執行塊清理,——清除儲存在資料塊的首部的與鎖有關的資訊,

8)已經知道了commit 所做的事情了,那麼考慮一下是頻繁提交好還是批次提交好呢?

頻繁的COMMIT會引起大量Redo Log的物理I/O,會極大的限制資料庫的效能 
因此,為提高資料庫效能,儘可能的批次提交,

9)前面提到redo log buffer 中的資訊寫入到redo log file,那麼redo log file 是個什麼東西呢?它實際上是記錄著對資料庫的所有修改,以防止資料的丟失,對資料庫來說非常重要,

便於安全的考慮,聯機重做日誌檔案至少分兩個組,一個組來記錄新的日誌檔案,另一個組來歸檔。這樣滿足寫機制,1.迴圈覆寫,2.寫滿切換日誌組,3.也可以手工切換日誌組:alter system switch log file; 那麼你自然會想到是誰幹寫了這件事,

這是LGWR程式完成的操作,觸發它寫的條件有:1.任何使用者commit的時候,2.當redo log buffer中的日誌有1/3滿時,3.有1M的日誌時,4.在DBWn寫之前,5.每三秒寫一次

11)上面說到歸檔--可以理解為對聯機重做日誌的複製,有了歸檔你就能保證資料永遠都不會丟失,是ARCn程式完成此操作的, 但重做日誌檔案切換組的時候(假如有兩個日誌組),如果另一個還沒有完成歸檔,這樣會出問題,資料庫夯住。。。

12pmon (程式檢測程式) :當會話異常終止時 清除失敗的程式 包括 回滾事務、釋放鎖,動態註冊監聽器。

13Smon (系統檢測程式):例項恢復(前滾所有重做日誌中的改變、回滾沒有提交的事務),釋放臨時表空間。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8494287/viewspace-1349469/,如需轉載,請註明出處,否則將追究法律責任。

相關文章