ORACLE的動態註冊行為 zt

asword發表於2009-10-22
[@more@]

大家都知道,ORACLE例項在啟動時,或使用命令ALTER SYSTEM REGISTER 或每隔一分鐘,例項的PMON會向監聽進行註冊,告知監聽,例項的服務名,例項名等資訊。

不同的平臺有不同的行為,本文所描述的是在LINUX下的行為。ORACLE版本為10.2.0.1。

講到動態註冊,跟監聽密切相關,下面先看看監聽的行為:

監聽在啟動時,會從$ORACLE_HOME/network/admin/listener.ora讀取監聽配置,如果該檔案不存在,則監聽會在 主機名對應的IP和1521埠上進行監聽。如果主機名在/etc/hosts裡沒有配置(或不能透過DNS解析---這是我的猜想,沒有驗證),則在等 待較長一段時間後,將在所有的地址上(0.0.0.0:1521)進行監聽,但此時例項並不會進行動態註冊,客戶端可透過主機的任意IP地址連線,但均會 報ORA-12514錯誤。除非設定LOCAL_LISTENER引數,將本地LISTENER地址指向本機的任意一IP。

如果存在listener.ora檔案,則監聽會根據該檔案配置內容進行啟動。如果主機名在/etc/hosts沒有條目,監聽 啟動比較慢(可能是監聽起來後,在根據主機名作什麼操作),因此必須要保證主機名要在/etc/hosts中有記錄。

同一個網路介面(網路卡)上,如果繫結了兩個或以上的IP地址,則監聽這樣的網路介面時,最多隻能使用一個主機名,比如:

[oracle@xty ~]$ cat /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain localhost
192.168.0.114 xty
192.168.0.115 xty_vip
192.168.0.116 xty_vip2

這裡xty和xty_vip對應的IP繫結在同一網路卡上

cat listener.ora

# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oracle/oracle/product/10.2.0/db_1)
(PROGRAM = extproc)
)
)

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = xty_vip )(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = xty )(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = xty_vip2 )(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
)
)

啟動監聽時,報下面的錯誤:

TNSLSNR for Linux: Version 10.2.0.1.0 - Production
System parameter file is /u01/app/oracle/oracle/product/10.2.0/db_1/network/admi
n/listener.ora
Log messages written to /u01/app/oracle/oracle/product/10.2.0/db_1/network/log/l
istener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521
)))
Error listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=xty)(PORT=1521)))
TNS-12542: TNS:address already in use
TNS-12560: TNS:protocol adapter error
TNS-00512: Address already in use
Linux Error: 98: Address already in use

Listener failed to start. See the error message(s) above…

將listener.ora中的(ADDRESS = (PROTOCOL = TCP)(HOST = xty )(PORT = 1521))行,改為(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.114 )(PORT = 1521)),則監聽能夠正常啟動

下面再來看一下PMON向監聽註冊例項的行為:

在預設情況下(也就是沒有LOCAL_LISTENER引數配置的情況下),PMON會根據主機名(hostname),查詢其IP地址,通常是在 /etc/hosts中找對應的條目,如果沒有找到hostname的IP地址,則PMON不會註冊,同時,必須是本機的IP地址,PMON才能註冊。比 如在/etc/hosts中將hostname對應的IP地址改為其他非本機的IP地址,PMON也不會進行註冊。PMON根據hostname找到IP 後,同時判斷這個是本機IP,則會透過這個IP連線至監聽進行註冊。如果listener沒有監聽這個IP,則PMON也不會註冊,因為透過這個IP連線 不上監聽。

舉一個簡單的例子,現有兩臺IBM小機,作雙機熱備,雙機採用HACMP。在監聽設定中,只監聽了HA的服務IP地址,而hostname對應的 IP地址為服務IP繫結的網路卡上的另一個地址。在這種情況下,PMON不能進行動態註冊,在客戶端連線這個ORACLE伺服器時,將會報ORA- 12514錯誤。

解決上面提到的這個問題的辦法,除了靜態註冊(本文主要討論動態註冊),還有兩種辦法,第一種我個人認為最好的一種,是在LISTENER上監聽兩個IP地址,類似於下面這樣:

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = xty_vip )(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.114 )(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
)
)

另一個辦法就是設定LOCAL_LISTENER引數,假如LISTENER只監聽了xty_vip(192.168.0.115)這個地址,則透過下面的命令設定LOCAL_LISTENER:

ALTER SYSTEM SET LOCAL_LISTENER=’ (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.115 )(PORT = 1521))’

這裡建議使用IP地址,特別是對RAC,後文細述。

LOCAL_LISTENER使PMON改變用hostname連線LISTENER進行註冊的預設行為。改而用LOCAL_LISTENER引數 指定的地址連線LISTENER進行註冊。當然LOCAL_LISTENER指定的IP地址必須是本機的IP地址。如果是非本機IP,則會忽略此引數,但 是會從前一個已註冊的監聽中取消註冊。

與LOCAL_LISTENER對應的引數有REMOTE_LISTENER引數。REMOTE_LISTENER使PMON在遠端(即非本機)監聽上進行註冊,這個引數在RAC中經常使用(用於負載均衡)。

下面來作一個:

主機1,LINUX AS4
主機2,Windows 2003,IP地址:192.168.0.100

,在主機2上啟動監聽:
D:oracleproduct10.2.0db_1BIN>lsnrctl start

LSNRCTL for 32-bit Windows: Version 10.2.0.1.0 - Production on 02-2月 -2008 09:5
6:44

Copyright (c) 1991, 2005, Oracle. All rights reserved.

啟動tnslsnr: 請稍候…

TNSLSNR for 32-bit Windows: Version 10.2.0.1.0 - Production
寫入d:oracleproduct10.2.0db_1networkloglistener.log的日誌資訊
監聽: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=dreamf)(PORT=1521)))

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
LISTENER 的 STATUS
------------------------
別名 LISTENER
版本 TNSLSNR for 32-bit Windows: Version 10.2.0.1.0 - Produ
ction
啟動日期 02-2月 -2008 09:56:47
正常執行時間 0 天 0 小時 0 分 3 秒
跟蹤級別 off
安全性 ON: Local OS Authentication
SNMP OFF
監聽程式日誌檔案 d:oracleproduct10.2.0db_1networkloglistener

監聽端點概要…
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=dreamf)(PORT=1521)))
監聽程式不支援服務
命令執行成功

在主機1上啟動監聽:
[oracle@xty ~]$ lsnrctl start

LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 01-FEB-2008 17:28:57

Copyright (c) 1991, 2005, Oracle. All rights reserved.

Starting /u01/app/oracle/oracle/product/10.2.0/db_1/bin/tnslsnr: please wait…

TNSLSNR for Linux: Version 10.2.0.1.0 - Production
System parameter file is /u01/app/oracle/oracle/product/10.2.0/db_1/network/admi
n/listener.ora
Log messages written to /u01/app/oracle/oracle/product/10.2.0/db_1/network/log/l
istener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521
)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.114)(PORT=1521
)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC0)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=xty_vip)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 10.2.0.1.0 - Production
Start Date 01-FEB-2008 17:28:57
Uptime 0 days 0 hr. 0 min. 0 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/oracle/oracle/product/10.2.0/db_1/network/adm
in/listener.ora
Listener Log File /u01/app/oracle/oracle/product/10.2.0/db_1/network/log
/listener.log
Listening Endpoints Summary…
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.114)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC0)))
Services Summary…
Service "PLSExtProc" has 1 instance(s).
Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service…
The command completed successfully
[oracle@xty ~]$

然後在主機1上啟動資料庫。輸入命令:

alter system set remote_listener=’(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.100)(PORT=1521))’;

在主機2上檢視LISTENER的狀態

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
LISTENER 的 STATUS
------------------------
別名 LISTENER
版本 TNSLSNR for 32-bit Windows: Version 10.2.0.1.0 - Produ
ction
啟動日期 02-2月 -2008 09:56:47
正常執行時間 0 天 0 小時 16 分 54 秒
跟蹤級別 off
安全性 ON: Local OS Authentication
SNMP OFF
監聽程式日誌檔案 d:oracleproduct10.2.0db_1networkloglistener.log

監聽端點概要…
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=dreamf)(PORT=1521)))
服務摘要..
服務 "XTY" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
服務 "XTY1XDB" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
服務 "XTY_XPT" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
命令執行成功

在主機2上再執行lsnrctl service命令:

D:oracleproduct10.2.0db_1BIN>lsnrctl service

LSNRCTL for 32-bit Windows: Version 10.2.0.1.0 - Production on 02-2月 -2008 10:
5:21

Copyright (c) 1991, 2005, Oracle. All rights reserved.

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
服務摘要..
服務 "XTY" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"DEDICATED" 已建立:0 已拒絕:0 狀態:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=xty)(PORT=1521))
服務 "XTY1XDB" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"D000" 已建立:0 已被拒絕:0 當前: 0 最大: 1022 狀態: ready
DISPATCHER
(ADDRESS=(PROTOCOL=tcp)(HOST=xty)(PORT=32801))
服務 "XTY_XPT" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"DEDICATED" 已建立:0 已拒絕:0 狀態:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=xty)(PORT=1521))
命令執行成功

主機1上的例項已經成功註冊到主機2上的監聽

在主機2上的TNSNAMES.ORA中有:

XTY_R =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = xty)
)
)

在主機2上連線XTY_R(這個例項實際執行在主機1上)

D:oracleadminXJbdump>sqlplus test/test@xty_r

SQL*Plus: Release 9.2.0.1.0 - Production on 星期六 2月 2 10:19:41

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

ERROR:
ORA-12535: TNS: 操作超時

請輸入使用者名稱:

報了ORA-12536錯誤。

從上面的lsnrctl service命令可以檢視到REMOTE SERVER的地址為:
(ADDRESS=(PROTOCOL=TCP)(HOST=xty)(PORT=1521))
因此客戶端連線時,LISTENER判斷這是個遠端SERVER,會將這個地址返回給客戶,客戶端再去連線這個地址。但這裡HOST=xty,客戶端不能解析這個地址,所以就報超時錯誤。

但如果在主機1上的資料庫中執行下面的命令:
alter system set local_listener=’(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521))’;

我們再看看主機2上的LISTENER SERVICE:

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
服務摘要..
服務 "XTY" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"DEDICATED" 已建立:0 已拒絕:0 狀態:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521))
服務 "XTY1XDB" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"D000" 已建立:0 已被拒絕:0 當前: 0 最大: 1022 狀態: ready
DISPATCHER
(ADDRESS=(PROTOCOL=tcp)(HOST=xty)(PORT=32801))
服務 "XTY_XPT" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"DEDICATED" 已建立:0 已拒絕:0 狀態:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521))
命令執行成功

注意看到上面REMOTE SERVER已經變成了 (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521))
這個時候再次連線,由成功連線到ORACLE伺服器上:

D:oracleadminXJbdump>sqlplus test/test@xty_r

SQL*Plus: Release 9.2.0.1.0 - Production on 星期六 2月 2 10:39:25 2008

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

連線到:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL>

在RAC中,伺服器開啟了負載均衡,則客戶端有時連線時會出現ORA-12514錯誤,這裡需要設定LOCAL_LISTENER引數,以解決該問題。

注意:在透過REMOTE_LISTENER引數向遠端監聽註冊時,本地的LISTENER也需要處於啟動狀態,否則監聽中服務的狀態為BLOCKED狀態:

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
服務摘要..
服務 "XTY" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"DEDICATED" 已建立:1 已拒絕:0 狀態:blocked
REMOTE SERVER
(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521))
服務 "XTY1XDB" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"D000" 已建立:0 已被拒絕:0 當前: 0 最大: 1022 狀態: ready
DISPATCHER
(ADDRESS=(PROTOCOL=tcp)(HOST=xty)(PORT=32801))
服務 "XTY_XPT" 包含 1 個例程。
例程 "XTY1", 狀態 READY, 包含此服務的 1 個處理程式…
處理程式:
"DEDICATED" 已建立:1 已拒絕:0 狀態:blocked
REMOTE SERVER
(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.115)(PORT=1521))
命令執行成功

而這個時候客戶端連線報ORA-12516錯誤

另外,資料庫例項版本必須與LISTENER版本相容,否則不能進行動態註冊。

本文主要是透過實驗和分析網路包,然後進行總結的結果,沒有參考相關的理論文件。有所錯誤在所難免,歡迎討論。

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

相關文章