连接RAC数据库中单个实例(二)
http://blog.itpub.net/4227/viewspace-677272
有时候希望连接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参数。