假如,我們現在利用Select語句從數據庫查詢數據,Oracle數據庫是如何運作的呢?從中我們可以領悟到什麼呢?下面,就結合一條簡單的select語句,看看Oracle數據庫後台的運作機制。這對於我們之後的系統管理與故障排除非常有幫助。
第一步:客戶端把語句發給服務器端執行。
當我們在客戶端執行select語句時,客戶端會把這條SQL語句發送給服務器端,讓服務器端的進程來處理這語句。也就是說,Oracle客戶端是不會做任何的操作,他的主要任務就是把客戶端產生的一些SQL語句發送給服務器端。雖然在客戶端也有一個數據庫進程,但是,這個進程的作用跟服務器上的進程作用事不相同的。服務器上的數據庫進程才會對SQL語句進行相關的處理。不過,有個問題需要說明,就是客戶端的進程跟服務器的進程是一一對應的。也就是說,在客戶端連接上服務器後,在客戶端與服務器端都會形成一個進程,客戶端上的我們叫做客戶端進程;而服務器上的我們叫做服務器進程。所以,由於所有的SQL語句都是服務器進程執行的,所以,有些人把服務器進程形象地比喻成客戶端進程的“影子”。
第二步:語句解析。
當客戶端把SQL語句傳送到服務器後,服務器進程會對該語句進行解析。同理,這個解析的工作,也是在服務器端所進行的。雖然這只是一個解析的動作,但是,其會做很多“小動作”。
1、查詢高速緩存。服務器進程在接到客戶端傳送過來的SQL語句時,不會直接去數據庫查詢。而是會先在數據庫的高速緩存中去查找,是否存在相同語句的執行計劃。如果在數據高速緩存中,剛好有其他人使用這個查詢語句的話,則服務器進程就會直接執行這個SQL語句,省去後續的工作。所以,采用高速數據緩存的話,可以提高SQL語句的查詢效率。一方面是從內存中讀取數據要比從硬盤中的數據文件中讀取數據效率要高,另一方面,也是因為這個語句解析的原因。
不過這裡要注意一點,這個數據緩存跟有些客戶端軟件的數據緩存是兩碼事。有些客戶端軟件為了提高查詢效率,會在應用軟件的客戶端設置數據緩存。由於這些數據緩存的存在,可以提高客戶端應用軟件的查詢效率。但是,若其他人在服務器進行了相關的修改,由於應用軟件數據緩存的存在,導致修改的數據不能及時反映到客戶端上。從這也可以看出,應用軟件的數據緩存跟數據庫服務器的高速數據緩存不是一碼事。
2、語句合法性檢查。
當在高速緩存中找不到對應的SQL語句時,則數據庫服務器進程就會開始檢查這條語句的合法性。這裡主要是對SQL語句的語法進行檢查,看看其是否合乎語法規則。如果服務器進程認為這條SQL語句不符合語法規則的時候,就會把這個錯誤信息,反饋給客戶端。在這個語法檢查的過程中,不會對SQL語句中所包含的表名、列名等等進行SQL他只是語法上的檢查。
3、語言含義檢查。
若SQL語句符合語法上的定義的話,則服務器進程接下去會對語句中的字段、表等內容進行檢查。看看這些字段、表是否在數據庫中。如果表名與列名不准確的話,則數據庫會就會反饋錯誤信息給客戶端。
所以,有時候我們寫select語句的時候,若語法與表名或者列名同時寫錯的話,則系統是先提示說語法錯誤,等到語法完全正確後,再提示說列名或表名錯誤。若能夠掌握這個順序的話,則在應用程序排錯的時候,可以節省時間。
4、獲得對象解析鎖。
當語法、語義都正確後,系統就會對我們需要查詢的對象加鎖。這主要是為了保障數據的一致性,防止我們在查詢的過程中,其他用戶對這個對象的結構發生改變。對於加鎖的原理與方法,我在其他文章中已經有專門敘述,在這裡就略過不談了。
5、數據訪問權限的核對。
當語法、語義通過檢查之後,客戶端還不一定能夠取得數據。服務器進程還會檢查,你所連接的用戶是否有這個數據訪問的權限。若你連接上服務器的用戶不具有數據訪問權限的話,則客戶端就不能夠取得這些數據。故,有時候我們查詢數據的時候,辛辛苦苦地把SQL語句寫好、編譯通過,但是,最後系統返回個“沒有權限訪問數據”的錯誤信息,讓我們氣半死。這在前端應用軟件開發調試的過程中,可能會碰到。所以,要注意這個問題,數據庫服務器進程先檢查語法與語義,然後才會檢查訪問權限。
6、確定最佳執行計劃。
當語句與語法都沒有問題,權限也匹配的話,服務器進程還是不會直接對數據庫文件進行查詢。服務器進程會根據一定的規則,對這條語句進行優化。不過要注意,這個優化是有限的。一般在應用軟件開發的過程中,需要對數據庫的sql語言進行優化,這個優化的作用要大大地大於服務器進程的自我優化。所以,一般在應用軟件開發的時候,數據庫的優化是少不了的。
當服務器進程的優化器確定這條查詢語句的最佳執行計劃後,就會將這條SQL語句與執行計劃保存到數據高速緩存。如此的話,等以後還有這個查詢時,就會省略以上的語法、語義與權限檢查的步驟,而直接執行SQL語句,提高SQL語句處理效率。
第三步:語句執行。
語句解析只是對SQL語句的語法進行解析,以確保服務器能夠知道這條語句到底表達的是什麼意思。等到語句解析完成之後,數據庫服務器進程才會真正的執行這條SQL語句。