从Oracle 8i开始,欧博官网Oracle引入了动态服务注册(Dynamic Service Registration)的功能,所谓动态注册是指当实例启动之后,由后台进程PMON在监听器中注册数据库服务信息。在动态注册机制下,原来监听器中的SID_LIST部分将不再需要。
通过服务注册可以获得如下收益:
1.简化配置
服务注册可以减化监听器的配置,SID_LIST_<listener_name>参数将不再需要.
2.连接时Failover
在动态注册时,由数据库主动向监听器注册实例,因此监听器总是可以知道实例的状态,在RAC环境下,当某个数据库实例出现故障时,动态服务注册功能可以快速自动的Failover客户端请求到其他实例;而如果在静态注册模式下,监听器将首先启动一个专用服务器进程接受客户端请求,然后向数据库服务器发起连接,欧博随后才能发现实例已经停止,给出“Oracle not available”的错误提示,这个过程要缓慢低效得多。
3.运行时连接负载均衡
在RAC环境下,服务注册使得监听器能够向负载最轻的实例转发连接请求,从而实现运行时连接的负载均衡。
动态注册在Oracle 9i里是自动启用的,监听器文件可以不再需要,或者可以配置一个经过极大简化的监听器文件。现在一个简单的监听器配置可能类似如下示例(缺省的监听PLSExtProc是为外部存储过程调用而配置的):
LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.16.33.50)(PORT = 1521)) ) (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) ) ) ) SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /opt/oracle9/product/9.2.0) (PROGRAM = extproc) ) )这样监听器启动后可以看到如下信息:
bash-2.03$ lsnrctl start Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.16.33.50)(PORT=1521))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Solaris: Version 9.2.0.4.0 - Production Start Date 16-FEB-2007 20:42:27 Listener Parameter File /opt/oracle9/product/9.2.0/network/admin/listener.ora Listener Log File /opt/oracle9/product/9.2.0/network/log/listener.log Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.16.33.50)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC))) Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully已经启动的实例随后会将服务名(初始化参数中定义的SERVICE_NAMES)注册到监听器中:
bash-2.03$ lsnrctl status 。。。。。。。。。。。。。。。。。。。。 Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... Service "eygle" has 1 instance(s). Instance "testora9", status READY, has 1 handler(s) for this service... Service "julia" has 1 instance(s). Instance "testora9", status READY, has 1 handler(s) for this service... Service "testora9XDB" has 1 instance(s). Instance "testora9", status READY, has 1 handler(s) for this service... The command completed successfully动态注册的服务名,由于监听器确切地知道实例的状态,所以正常状态通常显示为READY,而对于静态注册的服务名,则状态显示为UNKNOW,这也是我们经常看到某些数据库的监听器会有如下显示的原因:
Services Summary... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... Service "hsbill" has 2 instance(s). Instance "hsbill", status UNKNOWN, has 1 handler(s) for this service... Instance "hsbill", status READY, has 1 handler(s) for this service...缺省情况下,实例使用数据库服务器主机名对应的IP地址和1521端口连接监听进行动态注册,如果监听器使用了服务器主机名或主机名对应的IP地址、缺省的1521端口及TCP协议,则无需任何特殊配置,Oracle就能执行动态注册。否则需要设置LOCAL_LISTENER参数。
对于专用服务器模式,参数可以设置为:
LOCAL_LISTENER=listener_alias对于共享服务器模式,参数可以设置为:
DISPATCHERS="(PROTOCOL=tcp)(LISTENER=listener_alias)"Listener_alias随后通过Oracle命名方式(例如tnsnames.ora文件)解析为其他协议地址。例如如果监听器监听端口为1522,可以设置初始化参数为:
LOCAL_LISTENER=listener1对于共享服务期模式,可以设置为:
DISPATCHERS="(PROTOCOL=tcp)(LISTENER=listener1)"在tnsnames.ora文件中listener1可以按如下方式解析:
listener1= (DESCRIPTION= (ADDRESS=(PROTOCOL=tcp)(HOST=prod-server)(PORT=1522)))同样,监听器还可以向远程服务器注册,例如在RAC环境中,配置监听器远程注册需要设置REMOTE_LISTENER参数,假定两个实例的实例名称分别为prod1和prod2,那么两个实例的REMOTE_LISTENER参数应该分别设置如下。
对于prod1服务器设置:
REMOTE_LISTENER=listener_prod2对于prod2服务器设置为:
REMOTE_LISTENER=listener_prod1在prod1服务器上的tnsnames.ora文件中可以如下配置listener_prod2命名:
listener_prod2= (DESCRIPTION= (ADDRESS=(PROTOCOL=tcp)(HOST=prod2-server)(PORT=1521)))在prod2服务器上的tnsnames.ora文件中可以如下配置listener_prod1命名:
listener_prod1= (DESCRIPTION= (ADDRESS=(PROTOCOL=tcp)(HOST=prod1-server)(PORT=1521)))而为了进一步简化,REMOTE_LISTENER参数的配置在RAC环境中可以相同,以下是来自Oracle 10g RAC环境中的示例,多个实例的参数设置相同:
SQL> show parameter remote_lis NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ remote_listener string LISTENERS_SMSDB这个设置可以通过手工方式修改,类似如下命令可以用于完成这一工作:
alter system set REMOTE_LISTENER = ‘LISTENERS_ALIAS’ scope=both sid=’*’;然后tnsnames.ora文件配置包含如下信息:
LISTENERS_SMSDB = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.200.13)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.200.14)(PORT = 1521)) )这样监听器启动之后就会同时自动在远程和本地进行注册,这个RAC数据库的初始化参数SERVICE_NAMES设置如下:
SQL> show parameter service_name NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ service_names string smsrac, smsdb以下输出是RAC环境中数据库的注册信息(做了适当简化):
[oracle@smsdbrac2 admin]$ lsnrctl status STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 10.2.0.4.0 - Production Start Date 05-MAY-2008 16:04:44 ------------------------ Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM2", status BLOCKED, has 1 handler(s) for this service... Service "smsdb" has 2 instance(s). Instance "smsdb1", status READY, has 1 handler(s) for this service... Instance "smsdb2", status READY, has 2 handler(s) for this service... Service "smsrac" has 2 instance(s). Instance "smsdb1", status READY, has 1 handler(s) for this service... Instance "smsdb2", status READY, has 2 handler(s) for this service... The command completed successfully对应于RAC环境,客户端的tnsnames.ora文件配置也有所不同,以下是一段RAC环境下客户端的配置示例。与单实例的不同之处在于地址列表段包含多个实例的地址信息,同时支持负载均衡和在多实例之间的FailOver切换:
SMSRAC = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.200.13)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.200.14)(PORT = 1521)) (LOAD_BALANCE = yes) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = smsrac) (FAILOVER_MODE = (TYPE = SELECT) (METHOD = BASIC) (RETRIES = 180) (DELAY = 5) ) ) )