Oracle执行SQL语句的过程
【轉自:http://blog.csdn.net/wzy0623/archive/2009/09/27/4599615.aspx】
當我們提交一條sql語句時,oracle會做哪些操作呢??
Oracle會為每個用戶進程分配一個服務器進程:service process(實際情況應該區分專用服務器和共享服務器),當service process接收到用戶進程提交的sql語句時,服務器進程會對sql語句進行語法和詞法分析。?
名詞解釋:?
語法分析:語句本身正確性。?
詞法分析:對照數據字典中檢查表,索引,視圖和用戶權限。?
檢查通過后,服務器進程會將sql語句轉變為ascii碼,并通過一個hash函數將ascii碼生成出一個hash值,服務器進程會到share pool中查詢此hash是否存在,如果存在,服務器進程會從sharepool中讀取已經解析好的語句來執行;如果不存在,則需要做以下步驟:生成執行計劃和生成執行編碼(請理解何為執行計劃)。解析完成后,Oracle會將sql語句本身代碼、hash值、編譯代碼、執行計劃和所有與該語句相關的統計數據存放到sharepool中。
注意:?
1 盡量寫相同的sql語句,因為即使是from語句中table順序的變化、查詢字段位置的變化,甚至只是大小寫的不同,都會促使oracle重新做一次硬解析。?
2 增大share_pool_size可以保留更多的緩存在內存中的sql語句執行計劃,也意味著共享sql的可能性的增大。
在生成編譯代碼后,service process會試圖從db_buffer中讀取是否存在相關的緩存數據。
下面我們分兩種情況來說明:?
1 db_buffer中不包含內存數據:service process會首先在表的頭部請求一些行鎖,申請成功后,將這些行所在的第一個block讀入db_buffer。此時如果db_buffer空閑空間不足,則會觸發寫操作—DBWr。如果db_buffer剩余的空間不夠存儲新數據,就會觸發DBWr進程,將db_buffer中臟數據寫入數據文件。騰出來的空間寫入新數據。?
???注意:?db_block是oracle最小的邏輯單位,即使我們所要求的數據只是一個block所包含的眾多行中的一行或幾行,我們仍然需要將整個block讀入db_buffer。db_block的大小可以設置為8k的整數倍,并且可以針對不同的表空間設置不同的db_block_size的大小,一般建議在select多的表上將db_block_size設置大一些,而dml操作多的表上設置的小一些。?
2 DBWr是寫數據進程,觸發DBWr進程的事件除了db_buffer空間不夠外,ckpt進程也是觸發DBWr的事件。
補充:?
1 段是oracle最小的拓展單位。?
2 ckpt進程:檢查點進程。將scn寫入日志文件,控制文件,數據文件頭,數據塊頭部。觸發ckpt進程的事件有alter system checkpoint,alter tablespace offline/begin back up和正常shutdown數據庫。?
3 scn:,system change number或者使用system commit number。scn號是oracle的邏輯時鐘標志,我們可以理解為在commit時才會發生變化。Scn號是維持數據一致的重要標志,oracle實現備份恢復的數據一致性就是通過scn來判斷。?
block讀入db_buffer后,service process會將這個塊頭部的SCN號和發生變更的行數據寫入回滾段。當用戶或者oracle回滾數據時就是通過回滾段和當前數據塊實現數據的往前回滾。
解釋:?
回滾段是用來保存修改數據的前映像數據的,作用是保持并發操作時的讀一致性,實現回滾等。回滾段過小會引發快照過舊錯誤。9i提供了專門的undo表空間,顯然如果表空間級別的調整大小要比調整回滾段容易的多。
注意:?
Insert操作:回滾段只需要記錄rowid,如果回退,只需將該記錄根據rowid刪除即可;?
Update操作:回滾段只需要記錄發生變化的字段的前映像值,回滾時用前映像值覆蓋更新值即可;?
Delete操作:回滾段記錄整行的數據,回滾時恢復整行數據;?
做imp/exp或者大批量事務處理時,需要為當前事務創建一個大的回滾段,并將其他回滾段offline。?
接著oracle會生成日志,server process會將被修改的數據的rowid、修改前的值、修改后的值、scn信息和回滾段中的相關信息寫入redo log buffer,當發生以下操作時,LGWr會將redo log buffer中的數據寫入磁盤上的online redo:時間超過1s、占用redo log buffer空間超過1/3、檢查點進程、alter switch logfile和DBWr進程之前。
注意:?
1 oracle中寫數據的順序為:1 讀入db_buffer;2 寫回滾段;3 寫redo log buffer;4 改寫db_buffer;5 寫日志文件;6寫數據文件;?
commit并不會觸發DBWr進程,即不會寫入數據,commit只會觸發寫日志操作和寫入scn號。但是任何的dml語句都會產生日志。?
當一個聯機日志文件寫滿后,LGWr會寫入下一個聯機日志,請記住聯機日志是循環寫,而控制文件是并發寫。如果設置了為歸檔模式,歸檔進程會將前一個聯機日志寫入歸檔文件。?
2 db_buffer中包含內存數據:首先判斷用戶執行的操作類型。?
Select操作:首先判斷db_buffer中的數據塊頭部是否存在事務,如果有,則說明數據塊中的數據正在被事務處理,回滾段中存儲著該數據的前映像,server price利用回滾段中的數據進行讀一致性重構;如果數據塊頭部不存在事務,則有可能該數據已經被事務處理完畢但仍然留在db_buffer中,這時會比較select語句中scn號和db_buffer中的數據塊頭部的scn號,前者小于后者則說明此數據已經發生更改,處理數據同上,如果前者大于等于后者,則該數據為非臟數據,直接讀取即可。?
Update操作:無論數據塊頭部是否存在事務,又或者scn號之間孰大孰小,都需要服務器進程到表的頭部申請行鎖,申請成功則繼續操作,不成功則等待加鎖直至成功。
總結
以上是生活随笔為你收集整理的Oracle执行SQL语句的过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 复制到win7系统记事本是乱码怎么办 w
- 下一篇: 华硕笔记本u盘启动不了怎么办 华硕笔记本