1、讲在前面
本文档仅适用于如下范围:Oracle以dedicate (专有)连接模式通过TCP/IP协议连接的场景。
2、监听的作用
在谈监听的作用之前,有必要先看看监听的工作原理图:
-
客户端进程发送连接请求到监听程序
-
监听程序创建服务器进程
-
监听程序将客户端进程的连接重定向到服务器进程,使客户端进程与服务器进程建立一对一的连接
由上文描述可知,监听的作用在于创建服务器进程,进而可以使客户端进程与服务器进程建立一对一连接。服务器进程用于代理客户端进程发出的命令。
3、监听的工作原理
1)形象的比喻
用个现实中例子来比喻监听。
我们假设一座医院就是一个服务器,所有的医疗技术、医疗设备就是数据库,医院里的科室就是数据库提供的服务,每个科室的名字即相当于数据库服务名。在每个科室下面,会有很多医生,这些医生就是服务器进程。
我们去医院看病,是直接去找医生的吗?当然不是,我们会先去柜台挂号,挂号窗口即可理解为监听程序。在挂号窗口,你首先要告诉值班护士你要挂什么科室的号,然后窗口给你挂号单并为你指定主治医生,最后你拿着挂号单去对应科室的办公室找主治医生。
但这里有两个问题需要思考:
-
持公务员医保卡的、持本地社保卡的、无本地社保卡的病人是不是都能在挂号窗口进行挂号呢?
-
挂号窗口怎么知道某个科室当前是否能提供服务呢?
这两个问题将通过后面的"3.2-监听中的host参数","3.3-服务的注册"两个章节来回答。
2)监听中的host参数
现在我们来回答第一个问题。
可将公务员医保系统、本地社保系统、其它系统分别视作三个网络,医院可以选择接入某个网络或某几个网络。针对每一个网络,医院都有单独的收款账户,这个收款账户可理解为IP地址。
监听文件中的配置项ADDRESS,有一个子项叫HOST,这个子项的值即表示某个挂号窗口启用了某个系统的收款功能。假如银行在三个系统(公务员医保、社保、无社保)中的收款账户分别是A1,B1,C1,如果监听配置内容如下:
(ADDRESS = (PROTOCOL = TCP)(HOST = B1)(PORT = 1521))
那么此时,持公务员医保卡的人和无本地社保卡的人是没法儿在挂号窗口挂号的。
这里插播一个典型错误。很多同事的监听配置项中,配置HOST=localhost 。然后在自己本机登陆的时候没有问题,而其它客户端连接却报错:" ORA-12541: TNS:no listener "。究其原因,就是因为localhost是医院的内部账户,它属于医院内部的金融系统,只服务于医院内部,而医院外部的病人是没法直接往这个账户上付款的,也就不能在该窗口上挂上号。
这里会有一个疑问:如果挂号窗口想同时启用所有系统的收款账户,怎么办?好办,只需要把HOST参数改为医院的名称(相当于计算机名)就行了。在对网络安全要求不高的环境中、或IP地址经常发生变动的环境中,建议将HOST设置为计算机名。
3)服务的注册
回到上文中提到的第二个问题:" 挂号窗口怎么知道某个科室当前是否能提供服务呢?"。
简单点说:通过注册来解决。
注册,就是告诉别人或某个系统关于我的信息。例如新生儿出生了,需要在民政系统注册。如果不注册,尽管你在这个世界上存在,但别人通过民政系统无法查询到你,在法律上你不存在。
科室的注册有两种方式,第一种方式通过计划表:某个科室将服务时间段计划预先打印出来并提交给挂号窗口,那这个挂号窗口在有病人挂号时,根据计划表判断该科室当前是否可以提供服务,如果可以提供服务,则发放挂号单,否则拒绝挂号。这种方式相当于监听的静态注册,静态注册在本文档中不详述;第二种方式更灵活,科室没有固定的服务时间计划表,当科室有医生来到医院时,他直接打电话去挂号窗口,告知该科室现在可以提供服务了。如果他工作一段时间后打算离开,他会再次打电话给挂号窗口,告知该科室现在不能提供服务了。这种方法相当于监听的动态注册,我们将主要关心这类注册方式。
那么问题来了,它怎么知道给哪个挂号窗口打电话呢,或者说他怎么知道挂号窗口的分机号呢?数据库里有一个参数:local_listener。该参数决定了动态注册时,会向哪个挂号窗口打电话。如果该参数为空,它会向分机号1521打电话(1521为监听默认端口),如果没打通,则每隔60s再打一次,直到打通。如果该参数不为空,它有两种写法:
-
直接指定挂号窗口的连接字符串,例如 : alter system set
Local_listener=' (DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = hostname)(PORT = 1521)));'
-
呼叫总台转机。总台给每个挂号窗口起了个别名,这个别名记录在tnsnames.ora中,例如给某个挂号窗口取名叫abc:
abc=(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = hostname)(PORT = 1521)))
然后直接告诉总台窗口别名就行了:
alter system set local_listener=abc;
它将根据Local_listener中记录的信息,也是每隔60s再打一次,直到打通。
如果觉得等60s时间太久,可以主动发出注册命令:
Alter system register;
4)查看已注册的服务
怎么知道哪些科室已经在挂号窗口注册了呢?ORACLE给我们提供了一个工具:lsnrctl
在使用该工具之前,首先要保证ORACLE_HOME与PATH两个环境变量均指向ORACLE服务器端的相应路径。例如我的环境变更设置情况如下图:
在CMD中输入:
Lsnrctl service [listener]
其中listener表示监听器的名称,默认为listener。
只在已经被注册的服务才能对外提供服务。
4、FAQ
1)如果所请求的服务没注册报什么错?
2)如果监听程序没启动报什么错?
3)如果监听配置项HOST的值属于其它网络报什么错?
4)没有监听是不是就没法连接到数据库?
当然不是。在使用TCP/IP协议连接到数据库时,确实必须要有监听程序。但在使用BEQ协议连接数据库时,则不需要。
BEQ协议是ORACLE的本地连接协议。要求客户端进程与服务器进程在同一台机器,并且客户端进程需要从服务器端的%PATH%路径下启动sqlplus,另外必须使用服务器端的%ORACLE_HOME%变量。说起来看似麻烦,实际上只需要将ORACLE_HOME与PATH两个环境变量指向服务器端相应的路径即可。然后使用
Sqlplus / as sysdba
即可无密码,无监听登陆。登陆后可执行数据库的开启、关闭等操作。