环境介绍:
11gr2 rac 双节点,两个network资源,network1作为应用访问,network2作为DG,OGG同步备份网络;对应的有两个本地监听LISTENER(端口1521),LISTENER_DG(1621),一个SCAN监听
昨晚趁着存储链路调整,修改了生产环境监听配置。
我们知道11Gr2 rac下,监听文件不再像原来在oracle用户下的$ORACLE_HOME/network/admin目录下了,而是变成了grid用户下的$ORACLE_HOME/network/admin目录下。因此监听的启停以及查看状态都是在grid用户下。
另外,11Gr2 对于监听文件,官方不推荐手动配置(vi),而是通过工具添加生成(srvctl)。我们之所以做监听变更也正是这个原因。一节点监听文件是正常工具生成的格式,二节点不是,从而导致查看集群信息时,二节点的监听状态一直是INTERMEDIATE,而且报错Not All Endpoints Registered。
一节点listener.ora:
LISTENER_DG=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_DG)))) # line added by Agent
LISTENER=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER)))) # line added by Agent
LISTENER_SCAN1=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN1)))) # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN1=ON # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_DG=ON # line added by Agent
二节点listener.ora:
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_SCAN1 = ON
LISTENER_DG =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = edw2-dg-vip)(PORT = 1621))
)
)
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER_DG = ON
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = sfpay-edw-db02)(PORT = 1521))
)
)
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER = ON
LISTENER_SCAN1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = LISTENER_SCAN1))
)
)
因此我们将二节点的的listener.ora修改成和一节点一致。做完变更后,将监听起来,发现监听集群信息正常:
ora.LISTENER.lsnr
ONLINE ONLINE sfpay-edw-db01
ONLINE ONLINE sfpay-edw-db02
ora.LISTENER_DG.lsnr
ONLINE ONLINE sfpay-edw-db01
ONLINE ONLINE sfpay-edw-db02
ora.net1.network
ONLINE ONLINE sfpay-edw-db01
ONLINE ONLINE sfpay-edw-db02
ora.net2.network
ONLINE ONLINE sfpay-edw-db01
ONLINE ONLINE sfpay-edw-db02
ora.LISTENER_SCAN1.lsnr
1 ONLINE ONLINE sfpay-edw-db01
然而查看LISTENER_DG的状态时,数据库服务一直注册不上,所以导致通过这个监听访问的客户端一直访问不了:
grid>>lsnrctl status LISTENER_DG
.......
The listener supports no services
The command completed successfully
但是LISTENER,SCAN监听的服务却是正常的,并且数据库服务也能注册上。
grid>>lsnrctl status LISTENER
.....Services Summary...
Service "+ASM" has 1 instance(s).
Instance "+ASM1", status READY, has 1 handler(s) for this service...
Service "biolapdb" has 1 instance(s).
Instance "biolapdb1", status READY, has 1 handler(s) for this service...
Service "biolapdbXDB" has 1 instance(s).
Instance "biolapdb1", status READY, has 1 handler(s) for this service...
The command completed successfully
因为我们这里使用的是动态监听,于是想到可能PMON只是向LISTENER注册了服务,而没有将服务注册到LISTENER_DG。而控制这个行为的参数是local_listener。于是我们查看:
sqlplus>>show parameter local_listener
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
local_listener string
发现为空。于是查了下这个参数得解释:
local_listener这个参数得作用就是告诉pmon把注册信息注册到local_listener指定的地址上,默认不指定的话,value为空,则会动态注册本地ip 的1521端口,即等价于:
local_listener=' (ADDRESS = (PROTOCOL = TCP)(HOST = 本机ip)(PORT = 1521))'
而其他端口,oracle是没法知道的。
这就解释了为什么LISTENER正常,而LISTENER_DG不正常,因为LISTENER_DG是用的1621端口。
因此到这里问题就好解决了,在两个节点将这两个监听都加入到local_listener中就可以解决:
alter system set local_listener='(DESCRIPTION= (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=edw1-dg-vip)(PORT=1621)) (ADDRESS=(PROTOCOL=TCP)(HOST= sfpay-edw-db01)(PORT=1521))))' scope=both sid='biolapdb1';
alter system set local_listener='(DESCRIPTION= (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=edw2-dg-vip)(PORT=1621)) (ADDRESS=(PROTOCOL=TCP)(HOST= sfpay-edw-db02)(PORT=1521))))' scope=both sid='biolapdb2';
alter system register;
或者local_listener='LISTENER,LISTENER_DG',
这样的前提是在tnsname.ora里将具体信息添加进去。
此时在查看LISTENER_DG监听,状态正常,服务正常。
-----------------------------------------------------------------------------------
但是当我查看其相同架构的数据库参数时,发现:
SQL> show parameter listen
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
listener_networks string ((NAME=network1)(LOCAL_LISTENE
R=SYPDB2_LOCAL)(REMOTE_LISTENE
R=db.sypay.sfp.com:1521)), ((N
AME=network2)(LOCAL_LISTENER=S
YPDB2_LOCAL_DG)(REMOTE_LISTENE
R=SYPDB_REMOTE_DG))
local_listener string
remote_listener string db.sypay.sfp.com:1521
listener_networks参数有值,local_listener参数是保持的默认值,但是其库上的LISTENER_DG是正常的。
此时参考了一下博客:http://www.lunar2013.com/2016/02/oracle-12c-rac-%E9%85%8D%E7%BD%AE%E7%AC%AC%E4%BA%8C%E4%B8%AA%E7%BD%91%E7%BB%9C%E5%92%8C%E7%9B%B8%E5%BA%94%E7%9A%84scan2.html
发现其中有一步骤:配置ORACLE数据库实例支持多个网络
于是,继续修改:
oracle >>vim tnsnames.ora
EDWDB1_LOCAL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = sfpay-edw1-vip)(PORT = 1521))
)
EDWDB2_LOCAL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = sfpay-edw2-vip)(PORT = 1521))
)
EDWDB1_LOCAL_DG =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = edw1-dg-vip)(PORT = 1621))
)
EDWDB2_LOCAL_DG =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = edw2-dg-vip)(PORT = 1621))
)
EDWDB2_REMOTE_DG =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = edw1-dg-vip)(PORT = 1621))
)
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = edw2-dg-vip)(PORT = 1621))
)
)
alter system set listener_networks='((NAME=network1)(LOCAL_LISTENER=EDWDB1_LOCAL)(REMOTE_LISTENER=db.edw.sfp.com:1521))','((NAME=network2)(LOCAL_LISTENER=EDWDB1_LOCAL_DG)(REMOTE_LISTENER=EDWDB2_REMOTE_DG))' scope=both sid='biolapdb1';
alter system set listener_networks='((NAME=network1)(LOCAL_LISTENER=EDWDB2_LOCAL)(REMOTE_LISTENER=db.edw.sfp.com:1521))','((NAME=network2)(LOCAL_LISTENER=EDWDB2_LOCAL_DG)(REMOTE_LISTENER=EDWDB2_REMOTE_DG))' scope=both sid='biolapdb2';
然后将local_listener置为空:
alter system set local_listener='' scope=both sid='biolapdb1';
alter system set local_listener='' scope=both sid='biolapdb2';
alter system set remote_listener ='' scope=both sid='biolapdb1';
alter system set remote_listener ='' scope=both sid='biolapdb2';
发现效果一样。
总结:出现这个问题的原因,其实最终归结于对监听器以及local_listener,remote_listener ,listener_networks这三个参数的不了解。
对于监听器,数据库将服务注册到监听器里。静态监听的话,服务都写在了listener.ora文件里,监听器启动的时候会自动将这些服务注册,而不管数据库服务的状态(即使数据库服务在close状态,客户端请求时,也能登录,只不过是idle状态);动态监听的话,listener.ora文件里没有具体的服务内容(SID_LIST_LISTENER),只有LISTENER内容,数据库在启动后,PMON进程会自动将数据库服务注册到该监听器上,不过PMON默认只注册到1521的监听器上,如果监听不是1521端口,此时就需要local_listener参数指定。或者当有多个动态监听时,想让PMON动态将服务注册到多个监听上时,则需要local_listener指定多个条目。
对于remote_listener,只当数据库服务和监听器不再同一台机器上时用到的。不过我们平时rac环境里更多的用处是在每个节点上将remote_listener指定为scan监听,这样scan监听就能监听每个节点的服务,从而能通过scan ip就能负载均衡的访问每个节点。(scan通过每个节点上的本地监听器来探测每个节点上的压力,从而将请求分发到合适的节点上,最终还是通过本地监听来访问数据库的)
对于listener_networks, 当有多个network网络,比如想给数据库添加专用的DG网络,减少因为备份传输引起的带宽资源不够。这样在DG网络上也会有自己的local_listener,以及remote_listener ,此时就可以使用listener_networks参数来指定值,该参数里包含了每个网络对应的name,local_listener,remote_listener 参数;所以当我们指定了listener_networks参数后,就无需指定
local_listener,remote_listener参数了。