我們知道,Oracle數據庫中的各個進程要完成某個特定的任務或一組任務,每個進程都會分配內部內存(PGA 內存)來完成它的任務。Oracle實例主要有3類進程:服務器進程、後台進程和從屬進程,本文我們主要介紹一下Oracle數據庫服務器進程的相關知識,關於後台進程和從屬進程我們會在後面的文章中繼續介紹。
Oracle實例主要有3 類進程:
(1)服務器進程(serverprocess):這些進程根據客戶的請求來完成工作。我們已經對專用服務器和共享服務器有了一定的了解。它們就是服務器進程。
(2)後台進程(backgroundprocess):這些進程隨數據庫而啟動,用於完成各種維護任務,如將塊寫至磁盤、維護在線重做日志、清理異常中止的進程等。
(3)從屬進程(slaveprocess):這些進程類似於後台進程,不過它們要代表後台進程或服務器進程完成一些額外的工作。
在某些操作系統(如Windows)上,Oracle使用線程實現,所以在這種操作系統上,就要把我們所說的“進程”理解為“線程”的同義詞。
“進程”一詞既表示進程,也涵蓋線程。如果你使用的是一個多進程的Oracle 實現,比如說UNIX 上的Oracle 實現,“進程”就很貼切。如果你使用的是單進程的Oracle 實現,如Windows上的Oracle 實現,“進程”實際是指“Oracle 進程中的線程”。所以,舉例來說,當我談到DBWn 進程時,在Windows 上就對應為Oracle 進程中的DBWn 線程
服務器進程
服務器進程就是代表客戶會話完成工作的進程。應用向數據庫發送的SQL 語句最後就要由這些進程接收並執行。
(1)專用服務器(dedicatedserver)連接,采用專用服務器連接時,會在服務器上得到針對這個連接的一個專用進程。數據庫連接與服務器上的一個進程或線程之間存在一對一的映射。
(2)共享服務器(sharedserver)連接,采用共享服務器連接時,多個會話可以共享一個服務器進程池, 其中的進程由Oracle 實例生成和管理。你所連接的是一個數據庫調度器(dispatcher),而不是特意為連接創建的一個專用服務器進程。
注意連接和會話之間的區別:
(1)連接(connection)就是客戶進程與Oracle 實例之間的一條物理路徑(例如,客戶與實例之間的一個網絡連接)。
(2)會話(session)則不同,這是數據庫中的一個邏輯實體,客戶進程可以在會話上執行SQL 等。多個獨立的會話可以與一個連接相關聯,這些會話甚至可以獨立於連接存在。
專用服務器進程和共享服務器進程的任務是一樣的:要處理你提交的所有SQL。當你向數據庫提交一個SELECT * FROM EMP 查詢時,會有一個Oracle 專用/共享服務器進程解析這個查詢,並把它放在共享池中(或者最好能發現這個查詢已經在共享池中)。這個進程要提出執行計劃,如果必要,還要執行這個執行計劃,可能在緩沖區緩存中找到必要的數據,或者將數據從磁盤讀入緩沖區緩存中。這些服務器進程是干重活的進程。在很多情況下,你都會發現這些進程占用的系統CPU 時間最多,因為正是這些進程來執行排序、匯總、聯結等等工作,幾乎所有工作都是這些進程做的。
專用服務器連接
在專用服務器模式下,客戶連接和服務器進程(或者有可能是線程)之間會有一個一對一的映射。如果一台UNIX 主機上有100 條專用服務器連接,就會有相應的100 個進程在執行。可以用圖來說明,如圖5-1 所示。
客戶應用中鏈接著Oracle 庫,這些庫提供了與數據庫通信所需的API。這些API 知道如何向數據庫提交查詢,並處理返回的游標。它們知道如何把你的請求打包為網絡調用,專用服務器則知道如何將這些網絡調用解開。這部分軟件稱為Oracle Net,不過在以前的版本中可能稱之為SQL*Net 或Net8。這是一個網絡軟件/協議,Oracle 利用這個軟件來支持客戶/服務器處理(即使在一個n 層體系結構中也會“潛伏”著客戶/服務器程序)。不過,即使從技術上講沒有涉及Oracle Net,Oracle 也采用了同樣的體系結構。也就是說,即使客戶和服務器在同一台機器上,也會采用這種兩進程(也稱為兩任務)體系結構。
這個體系結構有兩個好處:
(1)遠程執行(remoteexecution):客戶應用可能在另一台機器上執行(而不是數據庫所在的機器),這是很自然的。
(2)地址空間隔離(addressspace isolation):服務器進程可以讀寫SGA。如果客戶進程和服務器進程物理地鏈接在一起,客戶進程中一個錯誤的指針就能輕松地破壞SGA 中的數據結構。
共享服務器連接
共享服務器連接強制要求必須使用Oracle Net,即使客戶和服務器都在同一台機器上也不例外。如果不使用OracleTNS 監聽器,就無法使用共享服務器。如前所述,客戶應用會連接到Oracle TNS 監聽器,並重定向或轉交給一個調度器。調度器充當客戶應用和共享服務器進程之間的“導管”。圖5-2 顯示了與數據庫建立共享服務器連接時的體系結構。
在此可以看到,客戶應用(其中鏈接了Oracle 庫)會與一個調度器進程物理連接。對於給定的實例,可以配置多個調度器,但是對應數百個(甚至數千個)用戶只有一個調度器的情況並不鮮見。調度器只負責從客戶應用接收入站請求,並把它們放入SGA 中的一個請求隊列。第一個可用的共享服務器進程(與專用服務器進程實質上一樣)從隊列中選擇請求,並附加相關會話的UGA(圖5-2 中標有“S”的方框)。共享服務器處理這個請求,把得到的輸出放在響應隊列中。調度器一直監視著響應隊列來得到結果,並把結果傳回給客戶應用。就客戶而言,它分不清到底是通過一條專用服務器連接還是通過一條共享服務器連接進行連接,看上去二者都一樣,只是在數據庫級二者的區別才會明顯。
連接與會話
在一條連接上可以建立0 個、一個或多個會話。各個會話是單獨而且獨立的,即使它們共享同一條數據庫物理連接也是如此。一個會話中的提交不會影響該連接上的任何其他會話。實際上,一條連接上的各個會話可以使用不同的用戶身份。
在Oracle 中,連接只是客戶進程和數據庫實例之間的一條特殊線路,最常見的就是網絡連接。這條連接可能連接到一個專用服務器進程,也可能連接到調度器。如前所述,連接上可以有0 個或多個會話,這說明可以有連接而無相應的會話。另外,一個會話可以有連接也可以沒有連接。使用高級Oracle Net 特性(如連接池)時,客戶可以刪除一條物理連接,而會話依然保留(但是會話會空閒)。客戶在這個會話上執行某個操作時,它會重新建立物理連接。
連接(connection):連接是從客戶到Oracle 實例的一條物理路徑。連接可以在網絡上建立,或者通過IPC 機制建立。通常會在客戶進程與一個專用服務器或一個調度器之間建立連接。不過,如果使用Oracle 的連接管理器(Connection Manager ,CMAN),還可以在客戶和CMAN之間以及CMAN 和數據庫之間建立連接。
會話(session):會話是實例中存在的一個邏輯實體。這就是你的會話狀態(session state),也就是表示特定會話的一組內存中的數據結構。提到“數據庫連接”時,大多數人首先想到的就是“會話”。你要在服務器中的會話上執行SQL、提交事務和運行存儲過程。可以使用SQL*Plus 來看一看實際的連接和會話是什麼樣子,從中還可以了解到,實際上一條連接有多個會話的情況相當常見。
這裡使用了AUTOTRACE 命令,並發現有兩個會話。我們在一條連接上使用一個進程創建了兩個會話。以下是其中的第一個會話:
- SQL> select username, sid, serial#, server,paddr, status from v$session where username='SYS';
- USERNAME SID SERIAL# SERVER PADDR STATUS
- ------------------------------ -------------------- --------- -------- --------
- SYS 153 27 DEDICATED 3621B264 ACTIVE
以上PADDR 列是這個專用服務器進程的地址。
下面,只需打開AUTOTRACE來查看SQL*Plus 中所執行語句的統計結果:
- SQL> set autotrace on statistics
- SQL> select username, sid, serial#,server, paddr, status from v$session where username='SYS';
- USERNAME SID SERIAL# SERVER PADDR STATUS
- ------------------------------ -------------------- --------- -------- --------
- SYS 152 88 DEDICATED 3621B264 INACTIVE
- SYS 153 27 DEDICATED 3621B264 ACTIVE
- Statistics
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 0 consistent gets
- 0 physical reads
- 0 redo size
- 770 bytes sent via SQL*Net toclIEnt
- 385 bytes received via SQL*Netfrom clIEnt
- 2 SQL*Net roundtrips to/fromclIEnt
- 0 sorts (memory)
- 0 sorts (disk)
- 2 rows processed
此時有了兩個會話,但是這兩個會話都使用同一個專用服務器進程,從它們都有同樣的PADDR 值就能看出這一點。從操作系統也可以得到確認,因為沒有創建新的進程,對這兩個會話只使用了一個進程(一條連接)。
需要注意,其中一個會話(原來的會話)是ACTIVE(活動的)。這是有道理的: 它正在運行查詢來顯示這個信息,所以它當然是活動的。但是那個INACTIVE(不活動的)會話呢?那個會話要做什麼?這就是AUTOTRACE 會話,它的任務是“監視”我們的實際會話,並報告它做了什麼。
在SQL*Plus 中啟用(打開)AUTOTRACE 時,如果我們執行DML 操作(INSERT、UPDATE、DELETE、SELECT和MERGE),SQL*Plus 會完成以下動作:
(1)如果還不存在輔助會話[1],它會使用當前連接創建一個新會話。
(2)要求這個新會話查詢V$SESSTAT視圖來記住實際會話(即運行DML的會話)的初始統計值。
(3)在原會話中運行DML 操作。
(4)DML 語句執行結束後,SQL*Plus會請求另外那個會話(即“監視”會話)再次查詢V$SESSTAT,並生成前面所示的報告,顯示出原會話(執行DML 的會話)的統計結果之差。
如果關閉AUTOTRACE,SQL*Plus 會終止這個額外的會話,在V$SESSION 中將無法看到這個會話。你可能會問:“SQL*Plus 為什麼要這樣做,為什麼要另建一個額外的會話?”。原因是:如果使用同一個會話來監視內存使用,那執行監視本身也要使用內存。
如果在同一個會話中觀察統計結果,就會對統計結果造成影響(導致對統計結果的修改)。倘若SQL*Plus使用一個會話來報告所執行的I/O 次數,網絡上傳輸了多少字節,以及執行了多少次排序,那麼查看這些詳細信息的查詢本身也會影響統計結果。這些查詢可能自己也要排序、執行I/O 以及在網絡上傳輸數據等(一般來說都會如此!)。因此,我們需要使用另一個會話來正確地測量。
到目前為止,我們已經看到一條連接可以有一個或兩個會話。現在,我們想使用SQL*Plus 來查看一條沒有任何會話的連接。這很容易。在上例所用的同一個SQL*Plus 窗口中,只需鍵入一個“很容易誤解”的命令即DISCONNECT:
ops$tkyte@ORA10G> set autotrace off
ops$tkyte@ORA10G> disconnect
從技術上講,這個命令應該叫DESTROY_ALL_SESSIONS 更合適,而不是DISCONNECT,因為我們並沒有真正物理地斷開連接。
注意在SQL*Plus 中要真正地斷開連接,應該執行“exit”命令,因為你必須退出才能完全撤銷連接。不過,我們已經關閉了所有會話。
使用另一個用戶賬戶打開另一個會話,並查詢原用戶SYS。
- SQL> select username, sid, serial#,server, paddr, status from v$session where username='SYS';
- no rows selected
可以看到,這個賬戶名下沒有會話,但是仍有一個進程,相應地有一條物理連接(使用前面的ADDR值):
- SQL> select username, program fromv$process where addr = hextoraw('3621B264');
- USERNAME PROGRAM
- ---------------------------------------------------------------
- oracle Oracle@db1 (TNS V1-V3)
所以,這就有了一條沒有相關會話的“連接”。可以使用SQL*Plus 的CONNECT 命令(這個命令的名字也起得不恰當),在這個現有的進程中創建一個新會話(CONNECT命令叫CREATE_SESSION更合適):
- SQL> conn / as sysdba;
- Connected.
- SQL> select username, sid, serial#,server, paddr, status from v$session where username='SYS';
- USERNAME SID SERIAL# SERVER PADDR STATUS
- ------------------------------ -------------------- --------- -------- --------
- SYS 158 34 DEDICATED 3621B264 ACTIVE
可以注意到,PADDR 還是一樣的,所以我們還是在使用同一條物理連接,但是(可能)有一個不同的SID。我說“可能有”,是因為也許還會分配同樣的SID,這取決於在我們注銷時是否有別人登錄,以及我們原來的SID 是否可用。
到此為止,這些測試都是用一條專用服務器連接執行的,所以PADDR 正是專用服務器進程的進程地址。
關於Oracle數據庫服務器進程的相關知識就介紹到這裡了,希望本次的介紹能夠對您有所收獲!