上一篇 / 下一篇 2010-12-26 23:18:59 / 个人分类:oracle工作机制
一直想写写监听器。
Oracle监听器listener是一个重要的数据库服务器组件,在整个Oracle体系结构中,扮演着重要的作用。
监听器Lisener功能
从当前的Oracle版本看,Listener主要负责下面的几方面功能:
1、 监听客户端请求。监听器运行在数据库服务器之上,与Oracle实例(可为多个)相关关联,是一个专门的进程process,在windows的服务项目或者Linux的运行进程列表中,都会看到对应的运行进程。Windows上名为TNSLSNR,Linux/Unix平台上是lsnrctl。监听器守候在服务器制定端口(默认为:1521),监听客户端的请求。
2、 为客户端请求分配Server Process。监听器只负责接听请求,之后将请求转接给Oracle Server Process。在Oracle的服务模式下,客户端进程是不允许直接操作数据库实例和数据,而是通过一个服务进程Server Process(也称为影子进程)作为代理。监听器接受到请求之后,就向操作系统(或者Dispatcher组件)要求fork(或分配)一个Server Process与客户端相连。
3、 注册实例服务。本质上将,listener是建立实例和客户端进程之间联系的桥梁。Listener与实例之间的联系,就是通过注册的过程来实现的。注册的过程就是实例告诉监听器,它的数据库数据库实例名称instance_name和服务名service_names。监听器注册上这样的信息,对客户端请求根据监听注册信息,找到正确的服务实例名称。目前Oracle版本中,提供动态注册和静态注册两种方式。
4、 错误转移failover。Failover是RAC容错的一个重要方面功能,其功能是在数据库实例崩溃的时候,可以自动将请求转移到其他可用实例上的一种功能。可以提供很大程度上的可用性(Availability)功能。这个过程中,发现实例已经崩溃,并且将请求转移到其他实例上,就属于是listener的功能。
5、 负载均衡衡量。在RAC架构中,Oracle实现了负载均衡。当一个客户请求到来时,Oracle会根据当前RAC集群环境中所有实例的负载情况,避开负载较高的实例,将请求转移到负载较低的实例进行处理。在早期RAC版本中,负载轻重的衡量是根据监听器当前维护连接数目来确定的,而不是实时查看多实例的负载。RAC环境中的监听器之间进行沟通通信。
下面的部分,会从几个方面对监听器进行简单介绍。
监听器操作
监听器在Windows和Linux/Unix平台上,都是可以直接操作的。下面以Windows平台操作为例,其他平台类似。
在命令行窗口(CMD),输入lsnrctl,就可以进入监听器控制窗口。
C:\Documents and Settings\Administrator>lsnrctl
LSNRCTL for 32-bit Windows: Version10.2.0.1.0 - Production on 26-12月-2010 21:5
3:04
Copyright (c) 1991, 2005, Oracle. All rights reserved.
欢迎来到LSNRCTL,请键入"help"以获得信息。
LSNRCTL>
通过输入命令help,可以查看支持的监听器操作。下面仅介绍常用的几个。
1、 查看当前监听器状态
敲入status,可以查看当前监听器的状态,对应操作日志信息和服务注册信息等内容。如下:
LSNRCTL> status
//连接监听器的名称和信息:主机名+监听端口号
正在连接到(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=www-0e6111dff74)(PORT=1521)
))
LISTENER的STATUS
------------------------
别名 LISTENER
版本 TNSLSNR for 32-bit Windows: Version10.2.0.1.0 – Production//Listener版本信息,在一台机器多实例的情况下,很重要!因为版本对应向下兼容
启动日期 26-12月-2010 19:38:03//启动服务时间
正常运行时间 0天2小时23分51秒
跟踪级别 off //调试信息,可以设置针对监听器的跟踪
安全性 ON: Local OS Authentication //表明启动、关闭监听器的操作权限是通过OS验证实现的。也就意味着,可以对监听器设置密码项目,也是Oracle安全配置的一个重要方面;
SNMP OFF//SNMP协议开启情况
监听程序参数文件 D:\oracle\network\admin\listener.ora//使用的参数
监听程序日志文件 D:\oracle\network\log\listener.log//操作日志位置
监听端点概要...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=www-0e6111dff74)(PORT=1521)))
服务摘要..//当前已经注册在监听器中的服务列表
服务"PLSExtProc"包含1个例程。
例程"PLSExtProc",状态UNKNOWN,包含此服务的1个处理程序...
服务"orcl"包含1个例程。
例程"orcl",状态READY,包含此服务的1个处理程序...
服务"orclXDB"包含1个例程。
例程"orcl",状态READY,包含此服务的1个处理程序...
服务"orcl_XPT"包含1个例程。
例程"orcl",状态READY,包含此服务的1个处理程序...
命令执行成功
上面通过红字,已经对结果进行一定程度说明。其中,需要额外注意的下面几项内容。
监听程序参数文件 D:\oracle\network\admin\listener.ora//使用的参数
监听器启动时依据参数文件的,当然没有参数文件监听器也是可以启动,那时监听器依据默认的行为操作。这个参数指定了监听器参数文件的位置,listener.ora。这个文件是一个文本类型参数文件,描述了监听器监听端口,主机名称和静态注册信息。Listener.ora是随着数据库实例的建立之后,建立监听器的过程中动态配置的。
监听程序日志文件 D:\oracle\network\log\listener.log//操作日志位置
监听器日志,是一个记录和描述监听器工作和错误的信息库。通过仔细研究日志内容,可以帮助我们发现当前的监听器的问题、解决连接故障和深入理解监听器工作原理。
服务"orcl"包含1个例程。
例程"orcl",状态READY,包含此服务的1个处理程序...
上文中已经说明,监听器有注册功能,通过status命令(services命令同样效果)。可以查看到当前有什么服务被注册上,用来检查连接服务失败,是常用的工具。
2、开启/关闭监听器
监听器的行为受到参数文件的控制,我们有时候需要调整监听器的参数。调整监听参数的方法,可以通过Oracle提供的GUI界面完成,还可以通过手工修改listener.ora来完成。
因为参数文件listener.ora是一个文本文件。Oracle对于文本类型的参数文件,大多数情况下是不支持热加载的。Pfile和listener.ora都是如此。
使用界面GUI,就是使用Net Configuration Assistant来配置。配置完成后,配置程序会自动重新启动监听器程序,来加载修改的参数文件。如果采用手工修改listener.ora,就必须要手工的进行监听程序关闭和启动。
LSNRCTL> stop
正在连接到(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=www-0e6111dff74)(PORT=1521)
))
命令执行成功
LSNRCTL> start
启动tnslsnr:请稍候...
TNSLSNR for 32-bit Windows: Version10.2.0.1.0 - Production
系统参数文件为D:\oracle\network\admin\listener.ora
写入D:\oracle\network\log\listener.log的日志信息
监听: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=www-0e6111dff74)(PORT=1521)))
正在连接到(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=www-0e6111dff74)(PORT=1521)
))
LISTENER的STATUS
------------------------
别名 LISTENER
版本 TNSLSNR for 32-bit Windows: Version10.2.0.1.0 - Production
启动日期 26-12月-2010 22:32:34
正常运行时间 0天0小时0分2秒
跟踪级别 off
安全性 ON: Local OS Authentication
SNMP OFF
监听程序参数文件 D:\oracle\network\admin\listener.ora
监听程序日志文件 D:\oracle\network\log\listener.log
监听端点概要...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=www-0e6111dff74)(PORT=1521)))
服务摘要..
服务"PLSExtProc"包含1个例程。
例程"PLSExtProc",状态UNKNOWN,包含此服务的1个处理程序...
命令执行成功
这里多说一句关于监听器的参数配置。使用GUI可以满足大部分的情况,而且可以避免拼写错误引发的监听器故障(监听器不会检查配置项目的正确与否)。但是,在一些比较复杂的情况下,比如一台机器绑定多个IP的情况,或者RAC的复杂功能配置上,还是倾向于使用手工编写listener.ora的方法。
此外,lsnrctl提示行还提供了reload命令,可以在listener启动的情况下,重新加载文件和SID信息。但是笔者还是比较喜欢stop+start的组合。
如果是在windows平台下,启动关闭监听器还可以在系统服务项目列表中操作,效果是一样的。
了解了监听器工具,下期让我们看看监听器是怎么工作的。
上一篇 / 下一篇 2010-12-26 23:21:39 / 个人分类:oracle工作机制
监听器工作过程
下面我们谈谈监听器的工作过程。一般,监听器作为一个独立process在操作系统中运行,守候在特定网络端口(默认为:1521),等待客户端请求的到来。注意:我们在客户端配置命名服务的时候,输入的1521也就是为了与监听器程序建立连接。
当一个请求“如期而至”,监听器对照已经注册的服务列表,查找对应的数据库实例信息,获取到指定实例的ORACLE_HOME路径。相当于表明可以进行连接。
客户端与实例的交互不是直接的,是通过Server Process作为代理中介来实现的。所有指令SQL都是客户端通过Server Process发送到实例中,这种体系结构是Oracle对于实例和数据库文件一种保护机制。
当监听器获得请求之后,要从Oracle实例中分配一个Server Process与之对应。这里不同的Oracle连接方式存在一些差别。
如果是专用连接模式,也就是一个客户端连接对应一个Server Process。监听器就会向OS请求fork(创造)出一个Server Process,与监听器尝试交互。
如果是共享连接模式,也就是多个客户端共享一个Server Process(注意:这里还不是连接池)。监听器就会向Dispatcher进程(管理共享模式连接的进程)请求一个Server Process与之交互。
Server Process与监听器的连接,实际上就是相互信息的交换。Server Process将自身在OS中的进程编号、连接地址信息发给监听器。监听器将客户端信息传递给Server Process。
监听器获取到Server Process的信息之后,将其返回给客户端连接程序。客户端获取到信息之后,进行重连接,根据返回的信息与Server Process在制定的服务器端口进行联系。
直到这个时候,客户端程序才将连接用户名、密码等信息发给Server Process,进行登录验证等操作。监听器的工作也就到此结束。
这里面有一个技术细节,就是Server Process与客户端连接的时候,是允许不使用1521端口的。具体连接的端口,是带有随机因素的。在9i版本Windows平台下,如果安装了防火墙,只允许1521端口通信,是会带来一些连接问题。好在在其他平台上和之后的版本中,实现了一种端口共享技术,连接可以和监听器一起使用1521端口。
介绍了监听器工作原理,下面我们说说动静态注册的机制。
动静态注册机制
在上面的内容中,我们已经初步了解了注册的作用,就是实现数据库实例名和服务名注册到运行的监听器程序中。目前的Oracle,支持静态注册和动态注册两种注册方式。
静态注册顾名思义,就是显示的指定出监听器程序要为那个实例以哪个服务名做监听。在启动监听器的时候,监听程序是不知道所监听实例服务是否存在。直到有客户端请求指定的服务。
指定静态注册的位置是在listener.ora参数文件,下面是一个典型参数文件的结构。
# listener.ora Network Configuration File: D:\oracle\product\10.2.0\db_1\network\admin\listener.ora
# Generated by Oracle configuration tools.
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = D:\oracle)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = orcl)
(ORACLE_HOME = D:\oracle)
(SID_NAME = orcl)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
)
)
其中,SID_LIST配置节点中的SID_DESC就是配置静态注册的节点项目。SID_LIST里用来配置当前监听器注册的服务项目,通过多个SID_DESC进行配置,每个SID_DESC基本上就是一个配置项目。默认是动态注册的时候,只有PLSExtProc项目。
静态配置项目中,通过GLOBAL_NAME配置服务项目,通过SID_NAME指定数据库实例的名称,通过ORACLE_HOME配置Oracle数据库软件安装的基本目录。
动态注册是与静态注册相对应的一种注册方法。同样也是通过listener.ora进行配置。下面是一个典型的配置参数文件。
# listener.ora Network Configuration File: D:\oracle\product\10.2.0\db_1\network\admin\listener.ora
# Generated by Oracle configuration tools.
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = D:\oracle)
(PROGRAM = extproc)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = www-0e6111dff74)(PORT = 1521))
)
)
对比上面的静态注册文件,可以发现显示指定服务名称和数据库实例名的项目不见了。只有本地地址和监听器端口信息。
动态注册的动作是监听器所在主机上数据库实例完成。动态注册是Oracle上一个不能关闭的功能。实例的background process PMON,每隔一段时间(一到两分钟)就会将实例的参数信息注册到监听器上,实现动态注册。
注册的信息是数据库参数service_name和instance_name。可以通过Show Parameter命令查看。
SQL> show parameter instance_name;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
instance_name string orcl
SQL> show parameter service_names;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
service_names string orcl
一般数据库在建立的时候,这两个参数都是已经设置好的,不会轻易的发生变化。
如果instance_name参数没有设置,则系统会选取参数db_name作为实例名称返回。如果service_names没有设置,则会将db_name和db_domain两个参数组合成服务名实现注册。
值得注意的一个问题是,service_names参数是一个可以指定多个服务名称的参数,以逗号分隔。也就是说,一个Oracle实例时可以同时作为多个服务名向外提供服务的。Service_name是Oracle在新近版本中提出,替代SID_NAME的概念。使用Service的指定方式,多个Oracle实例就可以统一提供一致的数据访问服务(也就是RAC)。
通常,对instance_name和service_name两个参数,还是建议设置上。因为会在一定程度上影响到动态注册的效果。
如果没有显示的指定这两个参数,那么只有在数据库实例启动在监听器实例之后的时候,才会一次动态注册。一旦之后监听器重新启动,动态注册的信息就不会存在,而且很难再次注册上。所以,我们是推荐将这两个参数设置上的。
只有显示设置两个值的情况下,PMON才会周期性的将注册信息加以注册。通过命令行,也可以强迫PMON立即执行一次注册操作。
SQL> alter system register
2 ;
System altered
最后,我们聊一聊动态注册的作用,支持错误转移failover。注册操作的发动方是PMON后台进程,PMON是Oracle实例最重要的后台进程,很多资料和DBA都是以该进程的状态确定数据库实例的状态。PMON负责动态注册,如果不能进行动态注册,说明PMON已经失去了工作能力,也就意味着监听程序所服务的实例已经不能工作。
通过动态注册的机制,监听程序是可以知道所服务的服务器实例已经崩溃,对于客户端的请求,可以实现错误转移。
当然,我们这里谈到的崩溃是实例的崩溃。如果监听器程序崩溃了,情况又是另一种样子了。