連線RAC資料庫中單個例項(二)

yangtingkun發表於2010-11-03

有時候希望連線RAC資料庫時,只連線到其中某個例項。但是要實現這個目的,並不是僅僅透過設定TNSNAMES.ORA中服務名地址列表就可以實現的。

這篇描述REMOTE_LISTENER的影響。

連線RAC資料庫中單個例項(一):http://yangtingkun.itpub.net/post/468/508011

 

 

上一篇描述了即使TNSNAMES.ORA配置的服務名僅包含了一個地址,透過這個服務名仍然可能連線到RAC的多個例項上:

TESTRAC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.224)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = TESTRAC)
      (INSTANCE_NAME = TESTRAC1)
    )
  )

透過TESTRAC服務名進行連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

既然只配置了一個IP地址,那麼Oracle是如何將連線分佈到兩個例項上呢,其實這裡是初始化引數REMOTE_LISTENER起的作用。

SQL> SHOW PARAMETER REMOTE_LISTENER

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
remote_listener                      string      LISTENERS_TESTRAC

而服務名LISTENERS_TESTRAC在兩個節點上的配置都是:

LISTENERS_TESTRAC =
  (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = racnode1-vip)(PORT = 1521))
    (ADDRESS = (PROTOCOL = TCP)(HOST = racnode2-vip)(PORT = 1521))
  )

因此,Oracle可以透過這個REMOTE_LISTENER獲取到兩個例項對應的監聽,從而將連線釋出到兩個例項上,下面不修改TESTRAC服務名的配置,而只是去掉REMOTE_LISTENER初始化引數的設定:

SQL> ALTER SYSTEM SET REMOTE_LISTENER = '' SCOPE = MEMORY;

系統已更改。

這個語句對兩個例項同時生效,現在兩個例項上都已經不再設定REMOTE_LISTENER引數了,這時再測試TESTRAC服務連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

由於只存在節點1的地址,因此現在透過TESTRAC服務名只會連線到節點1上,如果將TESTRAC服務名對應的IP改為節點2

TESTRAC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.225)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = TESTRAC)
    )
  )

測試連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

下面嘗試修改一個例項的REMOTE_LISTENER引數設定:

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> ALTER SYSTEM SET REMOTE_LISTENER = 'LISTENERS_TESTRAC' SCOPE = MEMORY SID = 'testrac2';

系統已更改。

SQL> SHOW PARAMETER REMOTE_LISTENER

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
remote_listener                      string      LISTENERS_TESTRAC

檢查節點1上的REMOTE_LISTENER引數:

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SHOW PARAMETER REMOTE_LISTENER

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
remote_listener                      string

維持TESTRAC服務名配置,繼續指向節點2的地址,嘗試連線TESTRAC服務名:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

可以看到,似乎REMOTE_LISTENER的設定並沒有生效,因為這時連線仍然只能連線到例項2上,並不會連線到例項1上。

TESTRAC服務名配置的地址指向節點1

TESTRAC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.224)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = TESTRAC)
    )
  )

再次測試連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

連線分佈到兩個例項的現象又出現了。不過節點1上並沒有設定REMOTE_LISTENER引數,反倒出現了這個現象,而節點2上設定了REMOTE_LISTENER引數,反而沒有出現這個現象。

其實道理很簡單,如果例項設定了REMOTE_LISTENER引數,則例項會在REMOTE_LISTENER引數列出的所有監聽上進行註冊,這個過程型別本地監聽註冊過程。而如果沒有設定REMOTE_LISTENER,顯然就不會進行遠端監聽註冊。

對於節點2而言,設定了REMOTE_LISTENER引數,因此連線節點1的監聽時,節點1的監聽存在例項1和例項2兩個註冊例項,所以服務名指向節點1地址的連線會分別在兩個例項上。

而對於節點1,沒有設定REMOTE_LISTENER引數,因此節點2的監聽僅存在例項2的註冊資訊,顯然透過這個服務名只能連線到節點2上。

可以透過伺服器上的監聽資訊來驗證上面的論述:

bash-2.03$ hostname
racnode1
bash-2.03$ lsnrctl status

LSNRCTL for Solaris: Version 10.2.0.4.0 - Production on 02-11-2010 12:06:42

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

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
LISTENER
STATUS
------------------------
別名
                      LISTENER_RACNODE1
版本
                      TNSLSNR for Solaris: Version 10.2.0.4.0 - Production
啟動日期                  28-10
-2010 16:18:23
正常執行時間              4 19 小時 48 19

跟蹤級別                  off
安全性
                    ON: Local OS Authentication
SNMP                      OFF
監聽程式引數檔案
          /data/oracle/product/10.2/database/network/admin/listener.ora
監聽程式日誌檔案
          /data/oracle/product/10.2/database/network/log/listener_racnode1.log
監聽端點概要
...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.224)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.222)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
服務摘要
..
服務 "testrac" 包含 2 個例程。

 
例程 "testrac1", 狀態 READY, 包含此服務的 1 個處理程式...
 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式
...
服務 "testracXDB" 包含 2 個例程。

 
例程 "testrac1", 狀態 READY, 包含此服務的 1 個處理程式...
 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式
...
服務 "testrac_XPT" 包含 2 個例程。

 
例程 "testrac1", 狀態 READY, 包含此服務的 1 個處理程式...
 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式
...
命令執行成功

這是節點1的監聽資訊,包含了例項1和例項2兩個節點的資訊。

bash-2.03$ hostname
racnode2
bash-2.03$ lsnrctl status

LSNRCTL for Solaris: Version 10.2.0.4.0 - Production on 02-11-2010 11:26:02

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

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
LISTENER
STATUS
------------------------
別名
                      LISTENER_RACNODE2
版本
                      TNSLSNR for Solaris: Version 10.2.0.4.0 - Production
啟動日期                  29-10
-2010 08:59:29
正常執行時間              4 2 小時 26 32

跟蹤級別                  off
安全性
                    ON: Local OS Authentication
SNMP                      OFF
監聽程式引數檔案
          /data/oracle/product/10.2/database/network/admin/listener.ora
監聽程式日誌檔案
          /data/oracle/product/10.2/database/network/log/listener_racnode2.log
監聽端點概要
...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.225)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.223)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
服務摘要
..
服務 "testrac" 包含 1 個例程。

 
例程 "testrac2", 狀態 READY, 包含此服務的 2 個處理程式...
服務 "testracXDB" 包含 1 個例程。

 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式...
服務 "testrac_XPT" 包含 1 個例程。

 
例程 "testrac2", 狀態 READY, 包含此服務的 2 個處理程式...
命令執行成功

顯然節點2的監聽只包括例項2的資訊。這就是REMOTE_LISTENER引數對於連線資料庫例項的影響。

如果各個節點的REMOTE_LISTENER都設定為空,那麼TNSNAMES.ORA中配置的服務名指定一個地址就可以實現連線到指定例項的目的,不再需要設定INSTANCE_NAME引數。

 

上一篇描述了即使TNSNAMES.ORA配置的服務名僅包含了一個地址,透過這個服務名仍然可能連線到RAC的多個例項上:

TESTRAC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.224)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = TESTRAC)
      (INSTANCE_NAME = TESTRAC1)
    )
  )

透過TESTRAC服務名進行連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

既然只配置了一個IP地址,那麼Oracle是如何將連線分佈到兩個例項上呢,其實這裡是初始化引數REMOTE_LISTENER起的作用。

SQL> SHOW PARAMETER REMOTE_LISTENER

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
remote_listener                      string      LISTENERS_TESTRAC

而服務名LISTENERS_TESTRAC在兩個節點上的配置都是:

LISTENERS_TESTRAC =
  (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = racnode1-vip)(PORT = 1521))
    (ADDRESS = (PROTOCOL = TCP)(HOST = racnode2-vip)(PORT = 1521))
  )

因此,Oracle可以透過這個REMOTE_LISTENER獲取到兩個例項對應的監聽,從而將連線釋出到兩個例項上,下面不修改TESTRAC服務名的配置,而只是去掉REMOTE_LISTENER初始化引數的設定:

SQL> ALTER SYSTEM SET REMOTE_LISTENER = '' SCOPE = MEMORY;

系統已更改。

這個語句對兩個例項同時生效,現在兩個例項上都已經不再設定REMOTE_LISTENER引數了,這時再測試TESTRAC服務連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

由於只存在節點1的地址,因此現在透過TESTRAC服務名只會連線到節點1上,如果將TESTRAC服務名對應的IP改為節點2

TESTRAC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.225)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = TESTRAC)
    )
  )

測試連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

下面嘗試修改一個例項的REMOTE_LISTENER引數設定:

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> ALTER SYSTEM SET REMOTE_LISTENER = 'LISTENERS_TESTRAC' SCOPE = MEMORY SID = 'testrac2';

系統已更改。

SQL> SHOW PARAMETER REMOTE_LISTENER

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
remote_listener                      string      LISTENERS_TESTRAC

檢查節點1上的REMOTE_LISTENER引數:

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SHOW PARAMETER REMOTE_LISTENER

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
remote_listener                      string

維持TESTRAC服務名配置,繼續指向節點2的地址,嘗試連線TESTRAC服務名:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

可以看到,似乎REMOTE_LISTENER的設定並沒有生效,因為這時連線仍然只能連線到例項2上,並不會連線到例項1上。

TESTRAC服務名配置的地址指向節點1

TESTRAC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.224)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = TESTRAC)
    )
  )

再次測試連線:

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> CONN YANGTK/YANGTK@TESTRAC
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

連線分佈到兩個例項的現象又出現了。不過節點1上並沒有設定REMOTE_LISTENER引數,反倒出現了這個現象,而節點2上設定了REMOTE_LISTENER引數,反而沒有出現這個現象。

其實道理很簡單,如果例項設定了REMOTE_LISTENER引數,則例項會在REMOTE_LISTENER引數列出的所有監聽上進行註冊,這個過程型別本地監聽註冊過程。而如果沒有設定REMOTE_LISTENER,顯然就不會進行遠端監聽註冊。

對於節點2而言,設定了REMOTE_LISTENER引數,因此連線節點1的監聽時,節點1的監聽存在例項1和例項2兩個註冊例項,所以服務名指向節點1地址的連線會分別在兩個例項上。

而對於節點1,沒有設定REMOTE_LISTENER引數,因此節點2的監聽僅存在例項2的註冊資訊,顯然透過這個服務名只能連線到節點2上。

可以透過伺服器上的監聽資訊來驗證上面的論述:

bash-2.03$ hostname
racnode1
bash-2.03$ lsnrctl status

LSNRCTL for Solaris: Version 10.2.0.4.0 - Production on 02-11-2010 12:06:42

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

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
LISTENER
STATUS
------------------------
別名
                      LISTENER_RACNODE1
版本
                      TNSLSNR for Solaris: Version 10.2.0.4.0 - Production
啟動日期                  28-10
-2010 16:18:23
正常執行時間              4 19 小時 48 19

跟蹤級別                  off
安全性
                    ON: Local OS Authentication
SNMP                      OFF
監聽程式引數檔案
          /data/oracle/product/10.2/database/network/admin/listener.ora
監聽程式日誌檔案
          /data/oracle/product/10.2/database/network/log/listener_racnode1.log
監聽端點概要
...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.224)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.222)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
服務摘要
..
服務 "testrac" 包含 2 個例程。

 
例程 "testrac1", 狀態 READY, 包含此服務的 1 個處理程式...
 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式
...
服務 "testracXDB" 包含 2 個例程。

 
例程 "testrac1", 狀態 READY, 包含此服務的 1 個處理程式...
 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式
...
服務 "testrac_XPT" 包含 2 個例程。

 
例程 "testrac1", 狀態 READY, 包含此服務的 1 個處理程式...
 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式
...
命令執行成功

這是節點1的監聽資訊,包含了例項1和例項2兩個節點的資訊。

bash-2.03$ hostname
racnode2
bash-2.03$ lsnrctl status

LSNRCTL for Solaris: Version 10.2.0.4.0 - Production on 02-11-2010 11:26:02

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

正在連線到 (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
LISTENER
STATUS
------------------------
別名
                      LISTENER_RACNODE2
版本
                      TNSLSNR for Solaris: Version 10.2.0.4.0 - Production
啟動日期                  29-10
-2010 08:59:29
正常執行時間              4 2 小時 26 32

跟蹤級別                  off
安全性
                    ON: Local OS Authentication
SNMP                      OFF
監聽程式引數檔案
          /data/oracle/product/10.2/database/network/admin/listener.ora
監聽程式日誌檔案
          /data/oracle/product/10.2/database/network/log/listener_racnode2.log
監聽端點概要
...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.225)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.25.198.223)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
服務摘要
..
服務 "testrac" 包含 1 個例程。

 
例程 "testrac2", 狀態 READY, 包含此服務的 2 個處理程式...
服務 "testracXDB" 包含 1 個例程。

 
例程 "testrac2", 狀態 READY, 包含此服務的 1 個處理程式...
服務 "testrac_XPT" 包含 1 個例程。

 
例程 "testrac2", 狀態 READY, 包含此服務的 2 個處理程式...
命令執行成功

顯然節點2的監聽只包括例項2的資訊。這就是REMOTE_LISTENER引數對於連線資料庫例項的影響。

如果各個節點的REMOTE_LISTENER都設定為空,那麼TNSNAMES.ORA中配置的服務名指定一個地址就可以實現連線到指定例項的目的,不再需要設定INSTANCE_NAME引數。

 

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

相關文章