日期:2014-05-16 浏览次数:20608 次
在Oracle data guard环境中,主库的alert.log文件出现"ORA-12514: TNS:listener does not currently know of service requested in connect descriptor"错误信息,导致主库上的日志无法传输到备库上,data guard数据同步不能实现。
这是一个最最基础的错误,在我们最初从客户端连接Oracle数据库时就可能碰到这个错误。
在主库上使用tnsping 这个oracle net服务别名,如下所示:
?
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.15.90)(PORT = 1844))) (CONNECT_DATA = (SERVICE_NAME = webdb))) OK (0 msec)
?
据此信息可以判断,数据库服务器上的监听器正常,客户端与数据库服务器的网络通讯正常,请求的端口184正常。问题仅仅是监听器不识别在连接符中提供的服务。
?
(miki西游 @mikixiyou 原文链接: http://mikixiyou.iteye.com/blog/1718387
)
问题分析
?
主库上请求连接备库的服务名webdb,在备库上不能被监听器识别。
在备库上,服务名webdb既没有被监听器动态注册,也没有静态配置在监听器配置文件listener.ora中。
这里解释一下注册的概念。?
我个人理解,注册就是将数据库实例作为一个服务写到到监听程序的监控列表中。
客户端连接数据库时,可以通过这个服务名直接申请到对应的数据库连接,而不再通过数据库实例或者数据库名称。这样客户端也就可以不用知道数据库实例和数据库名称。虽然服务名一般和实例名是一样的,但有这个功能后就可以不一样。
在数据库实例启动过程中,数据库实例严格地说是PMON进程会向监听器注册相应的服务。这个过程称为动态注册。
监听器程序在服务注册后,就记录了服务名和实例名之间的对应关系。从而使得客户端使用服务名访问时能从服务名可以转换到实例名。一个服务名下可以包含多个不同的实例名称,如RAC的下服务名;同样,一个实例名下,可以有多个不同服务名。服务名和实例名的对应关系PMON进程从数据库初始化参数service_names和instances中获取。
在服务名注册到监听器之后,客户端只需要通过服务名就能访问某个实例。在RAC下,这个服务名可以用来实现负载均衡和透明故障切换。
如果这时客户端还是使用实例名访问数据库,那么就不能实现RAC下的负载均衡和故障透明切换。
但是,动态注册不一定时时都生效的。如ORA-12514就是动态注册不生效,导致监听器无法识别客户端连接符中提供的服务名,从而拒绝建立数据库连接时报的错误信息。
动态注册默认仅仅注册到默认的监听器上,这个默认值有三项指标:名称是LISTENER、端口是1521、协议是TCP。如果需要向非默认监听注册,则需要配置local_listener参数。
使用tnsping得到的信息显示,监听器使用的端口号是1844,不是默认选项。因此,该服务名并没有被自动注册进入到监听器。
将这个服务注册进入监听器的方法还有一种,称之为静态注册。
静态注册是监听器启动时读取listener.ora配置,将实例和服务注册到监听程序。
监听器中对应的实例无论是否启动,都能通过lsnrctl services查询得到,但状态永远都是UNKNOWN。
无论何时启动一个数据库,默认地都有两条信息注册到监听器中:数据库服务器对应的实例和服务。
我们采用静态注册方法将webdb服务注册到监听器中,$ORACLE_HOME/network/admin/listener.ora中的内容设置如下:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oratt/product/10.2.0/dbhome_1)
(PROGRAM = extproc)
)
(SID_DESC =
(SID_NAME = webdb)
(ORACLE_HOME = /u01/app/oratt/product/10.2.0/dbhome_1)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = serv1)(PORT = 1844))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
)
)
?
其中这几行文字是为了静态注册webdb而加入的,如下:
(SID_DESC =
(SID_NAME = webdb)
(ORACLE_HOME = /u01/app/oratt/product/10.2.0/dbhome_1)
)
?
监听器的服务状况一直是UNKNOWN,不管注册使用的数据库实例是否打开。如下所示:
oratt@serv1:/home/oratt=>webdb$lsnrctl services
LSNRCTL for Linux: Version 10.2.0.4.0 - Production on 07-NOV-2012 13:37:56
Copyright (c) 1991, 2007, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=serv1)(PORT=1844)))
Services Summary...
Service "PLSExtProc" has 1 instance(s).
Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0
LOCAL SERVER
Service "webdb" has 1 instance(s).
Instance "webdb", status UNKNOWN, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:3 refused:0
LOCAL SERVER
The command completed successfully
?
因为这个监听器的端口号不是1521,所以采用了静态注册方法。
我们也可以不修改listener.ora文件,而采用配置local_listener参数的方法,将这个实例动态注册到监听器。
在数据库实例上修改local_listener参数,如下所示:
alter system set local_listener='(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.15.90)(PORT=1844))))';
修改之后,使用lsnrctl services检查监听器的服务状况,会发现有webdb注册进来,其状态是ready。发现该服务已经注册到监听器。
oratt@serv2:/home/oratt=>webdb$lsnrctl services
LSNRCTL for Linux: Version 10.2.0.4.0 - Production on 07-NOV-2012 13:55:38
Copyright (c) 1991, 2007, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HO