场景:
假设我们需要将多个oracle实例部署在同一套RAC集群/相同物理机上时,默认部署情况下,多个oracle实例共享使用默认的1521监听器。
监听器共享的使用方式会有几方面的问题:
- 不同实例的网络访问无法隔离,需要每个实例管理好自己的用户密码,避免访问到其他实例
- 如果有其中一个实例的短连接登录超频导致监听器响应慢,会影响到其他实例的登录访问
- 实例不具备独立的监听器配置, 比如wallet/tnsname/TDE/SSL/EUS认证等配置,无法给实例单独进行配置相关特性。
为保证网络隔离,并且支持并为不同实例设置不同的wallet/sqlnet/tnsnames/listener/TDE/SSL/EUS认证等配置,这里提供一个办法为每个实例配置单独的监听器,每个监听器设置不同的环境变量配置文件,并且讨论配置带来的操作规范要求和可能的影响;
监听器启动分析
一般来说,在单机实例上,可以通过修改$ORACLE_HOME/network/admin/listener.ora和lsnrctl命令创建监听:
在listener.ora中添加:
LISTENER_TEST =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = x.x.x.x)(PORT = 1524)(IP = FIRST))))
)
SID_LIST_LISTENER_TEST =
(SID_LIST =
(SID_DESC = (ORACLE_HOME = /u01/app/oracle/product)(SID_NAME = TEST)))
lsnrctl start LISTENER_TEST
lsnrctl status LISTENER_TEST
在RAC环境上,为实例添加独立的监听器的操作也是比较简单的:
DB用户:oracle
监听端口:1524
DB:test122
监听器名称:test122
su - oracle
srvctl add listener -listener test122 -oraclehome /u01/app/oracle/product -endpoints 1524
srvctl start listener -listener test122
通过这种方式启动后监听器的默认使用$ORACLE_HOME/network/admin目录下的listener.ora、tnsnames.ora、sqlnet.ora等配置文件;
如果我们需要多个版本相同的监听器,则这些配置文件在多个监听器之间是共享的。当需要为某个实例单独配置参数的时候,这种情况下就无法进行定制化修改。
我们可以以在启动监听器、database的时候通过设置监听器进程的环境变量TNS_ADMIN环境变量来修改默认listener.ora的路径,来为每个实例指定一个单独的监听器配置目录;
但是这里需要了解几种常见场景下oracle/listner的权限/环境变量引入方式:
- 命令行fork继承,比如sqlplus / as sysdba, lsnrctl start等,在服务器本地进行管理操作需要注意;
- 远程连接+dedicate server,继承监听器的环境变量(ORACLE_HOME/ORACLE_SID除外);
- 远程连接+shared server,集成DB进程的环境变量,DB进程的环境变量又可能来自于命令行/远程连接+静态监听;
数据库的环境变量和监听器环境变量的关系:
- 动态注册:db节点启动的时候pmon进程往监听器注册服务,并且将自身的环境变量传递给监听器;之后所有经过监听器启动的进程,都会应用pmon传递过来的环境变量;默认情况下pmon注册到1521的默认监听,可以通过local_listner参数配置注册到其他监听器;
备注:RAC实例创建后和srvctl创建监听器等情况下,默认使用动态注册的方式。SID_LIST_LISTENER_TEST =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = <db_name>)
(ORACLE_HOME = /u01/app/oracle/product/)
(SID_NAME = <sid_name>)
(ENVS="TNS_ADMIN=/u01/app/oracle/product/network/admin/<db_name>")
)
)
- 静态注册:通过listener.ora配置文件配置SID_LIST_listener_name参数,例如:
- 如果使用srvctl工具配置环境变量,相关配置会存储在OCR中,当srvctl启动相关服务的时候,会从ocr中读取并配置环境变量再启动服务;
- 最后, 一旦进程的环境变量设置,启动后再也没办法修改,如果修改需要重启进程(database/listener)
综合以上几种不同场景,解决办法:
- 为每个实例在$ORACLE_HOME/product/network/admin下创建<db_name>目录,存放listener.ora, tnsnames.ora, sqlnet.ora等配置
- 通过srvctl setenv为database和listener设置TNS_ADMIN参数,指向1中的目录
- 在进行实例管理操作(比如启停DB,监听器)的时候,需要设置TNS_ADMIN环境变量。
- 如果在listener.ora中配置静态监听,需要加上环境变量信息;
潜在的影响和操作规范(重要)
- 在RAC上操作实例、监听器尽量都通过srvctl进行操作,避免命令行lsnrctl/sqlplus连接直接操作。SID_LIST_LISTENER_TEST =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = <db_name>)
(ORACLE_HOME = /u01/app/oracle/product/)
(SID_NAME = <sid_name>)
(ENVS="TNS_ADMIN=/u01/app/oracle/product/network/admin/<db_name>")
)
)
- 如果通过命令行操作,由于fork环境变量继承,将会从命令行sqlplus/lsnrctl进程中的环境变量中带入oracle/tnslsnr进程,所以需要在机器上对单个实例的节点进行listener/database的启动/重启操作的时候,操作之前需要先加载对应实例的环境变量。
备注:可以在su切换用户的时候立即进行相关提示和列出环境变量配置操作,避免运维操作遗忘;
- 如果需要在listener.ora中配置静态监听,在ENVS的设置中带上实例应有的环境变量信息,例如:
- RAC环境中不要使用lsnrctl save_config <listener_name> 的方式修改listener.ora;
调试相关命令
调试相关:
- linux进程环境变量的查看方式:ps -ef找出所在进程pid,通过命令查看搜索环境变量
xargs --null --max-args=1 echo < /proc/58144/environ|grep -i tnssrvctl getenv database -d test122
srvctl getenv listener -l test122
-- 修改
srvctl setenv database -d test122 -t "TNS_ADMIN=/u01/app/oracle/product/network/admin/test122/"
srvctl setenv listener -listener test122 -t TNS_ADMIN=/u01/app/oracle/product/network/admin/test122/
-- 重启
srvctl stop listener -listener test122
srvctl start listener -listener test122
srvctl stop database -d test122
srvctl start database -d test122
- 通过srvctl工具查看存在ocr中的环境变量配置,配置或者修改变量,需要通过srvctl重启生效(命令行无效)
参考资料:
- EBS/RAC setting TNS_ADMIN for srvctl:http://ermanarslan.blogspot.com/2017/09/ebsrac-setting-tnsadmin-for-srvctl.html
- MOS:Dynamic Registration and TNS_ADMIN (Doc ID 181129.1)
- MOS:The Impact of the Sqlnet Settings on Database Security (sqlnet.ora Security Parameters and Wallet Location) (Doc ID 1240824.1)