Oracle9i中的監聽動態註冊

jss001發表於2009-02-22

在Oracle9i中,使用命令lsnrctl status可以看到如下例子:

Service "lrdb" has 2 instance(s).
Instance "lrdb", status UNKNOWN, has 1 handler(s) for this service...
Instance "lrdb", status READY, has 1 handler(s) for this service...

這是Oracle9i監聽器行為的不同之處的第一個線索,因為Instance "lrdb"出現了兩次。出現額外條目是因為,
資料庫在啟動時透過一個被稱為動態註冊的程式在監聽器中註冊資訊。相應地,如果資料庫透過listener.ora
檔案中的資訊在監聽器中註冊資料庫著稱為靜態註冊。在上面的輸出中,狀態UNKNOWN值的時靜態註冊的設定。
這是監聽器用來表明它不知道關於該例項的任何資訊的方式,只有當客戶發出連線請求時,它才檢查該例項是否
存在。

動態註冊的資料庫透過狀態資訊中的狀態READY或狀態BLOCKED(對於一個備用資料庫)來指明。不管何時資料庫
資料庫關閉,動態註冊的資料庫都會動態地從監聽器登出,而與之相關的資訊將從狀態列表中消失。這樣,不管
資料庫是在執行還是已經關閉,監聽器總是知道它的狀態。該資訊將被用於連線請求的回退(fallback)和負載
平衡。自我註冊功能是不能被關閉的(至少在任何可見的文件中是這樣),由於該功能帶來的好處,因此不能關閉
它也並不是件壞事。當您可以免費獲得資料庫的自我註冊功能時,為什麼還需要listener.ora檔案中的靜態註冊
條目呢?您對此感到疑惑,是嗎?答案是:除了幾種例外情況外,您根本不需要執行靜態註冊。這樣的結果是,只
要使用預設的監聽器埠1521,您就不再需要listener.ora檔案。然而,當(且僅當)要把日誌檔案和跟蹤資訊
儲存到標準目錄中時,您或許仍然會使用listener.ora檔案。

下面是資料庫的自我註冊過程(假設在資料庫啟動之前,監聽器已經啟動並在正常執行)。無論何時啟動一個資料
庫,預設地都有兩條資訊註冊到監聽器中:例項和服務。

註冊到監聽器中的例項值從init.ora檔案中的instance_name引數取得。如果該引數沒有設定值,那麼它將取init.ora
檔案中的db_name的值。在只有單個例項執行的情況下,您可以不必設定該引數,但最好將其設定為db_name的值,
以充分利用動態註冊功能。然後,如果在RAC中配置,您必須將叢集中每個例項的instance_name引數設定為一個唯
一的值。

註冊到監聽器中的服務值從init.ora檔案中的引數service_names取得。如果該引數沒有設定值,資料庫將拼接
init.ora檔案中的db_name和db_domain的值來註冊自己。如果選擇提供service_names值,您可以使用完全限定
的名稱(比如lrdb.oracle.com)或縮寫的名稱(比如lrdb)。如果選擇縮寫的名稱並設定了db_domain引數,注
冊到監聽器中的服務將是service_name值和db_domain值的拼接。例如下面的設定將導致服務lrdb.oracle.com
被註冊到監聽器中:
db_domain=oracle.com
service_name=lrdb

可選擇的,您可以在service_names引數中指定多個服務值,值之間用逗號格開;這對於共享伺服器配置是很有用的。
如果需要執行連線時故障轉移或負載均衡,或者想要在RAC中配置在例項之間透明地分佈連線,那麼使用service_names
引數將是必要的。為啟用這些功能,您只需要將每個例項的資料庫引數檔案中的service_names設定為同一個值,
並在客戶端連線請求的service_name設定中引用該值。

為初始化引數service_names和instance_name設定顯式的值是個很好的實踐,儘管如果您沒有設定它們,Oracle也
會為動態註冊而生成預設值(基於db_name和db_main)。這樣做的原因是,如果監聽器在資料庫啟動之後重新啟動,
其動態註冊行為將會有一些微妙的區別.如果監聽器在資料庫執行之後重新啟動,你們僅當您在init.ora檔案中顯式
地設定了service_names和instance_name的值時,每個資料庫的PMON程式才會在很短的時間之後自動註冊資料庫。
如果沒有顯式設定service_names和instance_name的值,那麼僅當資料庫在監聽器執行之後啟動時,動態註冊才會
發生;在這種情況下,如果監聽器後來發生了重啟,動態註冊資訊將會丟失。

顯然,最後在啟動任何資料庫之前啟動伺服器上的監聽器,並完全避免監聽器的重啟。另外,您還可以在SQL*PLUS中
使用ALTER SYSTEM REGISTER命令,在資料庫開啟時的任何時候,手工地在監聽器中註冊服務值。這個命令對於替換
因監聽器重啟而丟失地服務值很有用,並且它所註冊地值與在資料庫啟動時由動態註冊所設定的值完全一樣。

總而言之,Oracle9i透過listener.ora中的GLOBAL_DBNAME向外提供靜態服務,透過PMON讀初始化引數service_names、
instance_name向外提供動態(真實在執行的)服務。舉例如下:

listener.ora檔案內容

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /oracle/product/9.2.0.4)
(PROGRAM = extproc)
)
(SID_DESC =
(
GLOBAL_DBNAME = lrdb
)
(ORACLE_HOME = /oracle/product/9.2.0.4)
(SID_NAME = lrdb)
)
(SID_DESC =
(
GLOBAL_DBNAME = gsid
)
(ORACLE_HOME = /oracle/product/9.2.0.4)
(SID_NAME = lrdb)
)
)

該檔案使得這個單例項的資料庫lrdb,向外提供了兩個服務:lrdb和gsid

初始化引數設定:instance_name=lrdb service_name=lrdb,gsid

所以動態註冊時也會對外提供兩個服務:lrdb和gsid

最後透過lsnrctl status看到的情況就是:

Service "gsid" has 2 instance(s).
Instance "lrdb", status UNKNOWN, has 1 handler(s) for this service...
Instance "lrdb", status READY, has 1 handler(s) for this service...

Service "lrdb" has 2 instance(s).
Instance "lrdb", status UNKNOWN, has 1 handler(s) for this service...
Instance "lrdb", status READY, has 1 handler(s) for this service...

對外提供的服務gsid和lrdb都有兩個例項(一個靜態註冊一個動態註冊),狀態都分別是UNKNOWN和READY。

對於客戶端來說,它不用關心資料庫的名字、例項名到底是什麼,它只需要知道資料庫對外提供的服務名就行了,
這個名字可能和例項名一樣,也可能不一樣。

[@more@]

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

相關文章