“LOCAL_LISTENER”参数导致业务无法连接数据库,文末附Oracle连接故障检查监听的排查流程

1. 背景及问题

今天在Oracle BCV技术[1]做数据同步,建立生产库的测试库,需要DBA配合同步前后的停库和起库。在同步完起库后,有部门反应同步好的测试库连接不上去

2. 问题排查

以我当前的知识储备,能想到的可能就是以下几点进行检查:

  1. 数据库实例状态,是不是没有open ---> select status from v$instance;

  2. 监听器状态,是不是监听没起来 ---> lsnrctl status|start

  3. Oralce黑白名单配置问题 ---> $ORACLE_HOME/network/admin/sqlnet.ora

  4. 客户端 tnsnames.ora 配置问题,连接符写错了 ---> tnsping

  5. 网络连接问题,端口是否开放 ---> ping IP 、 telnet IP 1521

这些都不是,由于情况紧急,测试环境等着用,部门同事再三提示下,我还是不知道他们说的那个参数---LOCAL_LISTENER,这个就是引起这次数据库连接不上的罪魁祸首,导师一下就解决了👍!

我把生产的服务名拿到测试库注册了,导致测试库没有对外提供网络连接,只能通过本地访问数据库,通过将LOCAL_LISTENER该参数重置成默认参数、置空或者修改测试库的服务名就解决了,总之就是使测试库对外提供网络连接,但上面的问题还存在一个非常大的安全隐患,下面细说

3. 事后回顾

今天这个任务的流程是这样的:停库 ---> BCV同步测试数据 ---> 起库,1、3步骤是需要DBA配合来做的,因为是从其他库同步过来的数据,再数据库启动阶段Oracle会做一个数据库启动验证 ,其实就是对比各个文件数据是否一致,是否需要恢复,首先Oracle启动时会检查数据文件头 中的checkpoint cnt是否与对应控制文件 中的checkpoint cnt一致,如果一致,进行第二次检查,数据文件头的开始scn 和对应控制文件中的结束scn是否一致,如果结束scn等于开始scn,则不需要要对那个文件进行恢复,没问题启动数据库。

我拿其中一部分操作步骤来说今天这次事故发生的原因:

刚刚从生产同步过来的测试库,需要经历启动验证这个阶段,回过来,数据库起库三阶段,

  1. 加载参数文件 --》startup nomount

  2. 加载控制文件 --》startup mount

  3. 加载数据文件等所有文件--》startup (打开到open)

同步过来的测试库可能有日志文件不一致,先以RESETLOGS方式起库

扩展一: Resetlogs NoResetlogs 的区别

复制代码
alter database open RESETLOGS;

找到测试库控制文件位置,在后面的参数文件修改成本库的

复制代码
show parameter control_files

重点来了,关库,去同步的生产库创建一份参数文件:

复制代码
create pfile='/home/oracle/inittxxxx.ora' from spfile;

用生产库的参数文件起测试库,这份参数文件我只修改了两个参数

复制代码
*.cluster_database=FALSE
control_files

其中有关参数文件参数的介绍和管理部分,可参考我之前发的一篇文章:

Oracle 文件管理-参数文件、控制文件、归档 - 墨天轮

其中忽略了一个参数也就是本文的主角 local_listener-本地监听服务的名称。

测试库起库:

复制代码
shutdown immediate;
startup mount pfile='/home/oracle/inittxxxx.ora'; ---用pfile文件起库
alter database noarchivelog;
alter database open;

先介绍一下LOCAL_LISTENER参数, 该参数指定了数据库PMON进程需要将数据库实例注册到哪个端口,参数文件是这样配置的 local_listener

复制代码
*.local_listener='LISTENER_1523','LISTENER_TUX','LISTENER_1529','LISTENER'

扩展二:local_listener 与 remote_listener 设置监听

如果没有设置这个参数,PMON进程默认将数据库的服务注册到本地节点的1521端口,这还好说,我偏偏就指定了这个参数,这个参数是用于本地监听的服务名,也就是说,我把生产的服务名拿到测试库注册了。有什么影响呢?他可能会把当前的服务名按照连接符去生产在注册一遍。

所以问题解决了,为什么连不上库,因为没有该库没有对外提供测试库的监听,业务想要连接数据库需要通过网络连接,即**Listener连接到服务器,**但是测试库参数指定的监听服务的名称是生产库的,外面肯定连接不上来。

扩展三:连接(访问)数据库的两种方式:LOCAL=NO 和 LOCAL=YES

Oracle的监听就类似与开发中的封装思想, 将对象的属性和方法隐藏起来,通过公开的接口提供对这些属性和方法的访问。 而Oracle监听器(Listener)责管理客户端与数据库实例之间的连接,当客户端发起连接请求时,监听器接收该请求,并将其引导至适当的数据库服务。监听器隐藏了数据库实例的复杂性,只对外提供统一的接口------服务名和连接字符串,让客户端不需要了解数据库实例的具体配置和位置,也可提供服务。

Oracle Listener 可以视为数据库的"前门",它通过监听网络上的连接请求,封装了数据库的物理细节,比如IP地址、端口号、实例名等,Oracle 将客户端和服务器彻底隔离开来,客户端通过配置的连接字符串、服务名就可以连接到数据库,而不需要知道数据库的内部结构和配置细节,对于客户端来说,它不用关心数据库的名字、实例名到底是什么,它只需要知道数据库对外提供服务。

关于数据库的访问,这里引用一下**盖总《深入解析Oracle》**一书中的介绍,

数据库启动之后,要想提供网络服务,通过远程连接访问,我们还需要启动数据库的监听器(配置文件通常为 listener.ora),监听器用于在特定的端口上(缺省的端口是 1521)提供监听,接收来自客户端的访问请求(客户端请求通过 tmnsnames.ora 文件定义发送)。在专用服务器模式下(Dedicated Server),监听器会为每个请求衍生一个服务器进程相对应,通过这个服务器进程将客户端与数据库联系起来。下图描述了建立网络连接时客户端以及服务器端的相关文件及关系:

该书虽然出版的早,但是文章对Oracle数据库的讲解非常全面,通俗易懂,很适合当学习教材。

常用的配置文件介绍

以下是Oracle网络配置文件的简洁描述:

  1. ldap.ora
  • 配置LDAP目录名称解析,允许通过LDAP查询数据库服务信息。
  1. cman.ora
  • 配置Oracle连接管理器参数,用于管理和路由客户端连接。
  1. tnsnames.ora
  • 配置本地或远程客户端的本地名称解析,定义数据库服务的网络地址映射。
  1. listener.ora
  • 配置监听器的注册信息,指定监听的数据库服务和网络参数。
  1. sqlnet.ora
  • 配置服务器或客户端的网络协议支持、解析方式、安全、认证等设置。

上面提到测试库注册了生产库的服务名,但是因为是是别名,在测试库的tnsname.ora里并没有识别到,还有一种写法,可以直接写连接符,如下

复制代码
SQL> alter system set local_listener='ADDRESS=(PROTOCOL=TCP)(HOST=192.168.60.101)(PORT=1521)'; 
SQL> show parameter local_listener;
NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
local_listener			     string	  (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.60.101)(PORT=1521))

但如果测试库的tnsname.ora配置了一样的名字,成功识别到了这些信息,将信息注册到生产库上会造成什么影响呢?可能有两种可能

1、服务名一样,IP一样

2、服务名一样,IP不一样

4. 测试和验证- Oracle测试库与生产库使用相同服务名的影响分析及验证

后面单独写一篇文章来测试吧!

5. 总结 --- Oracle 客户端无法连接之监听的分析流程

还有什么情况连接不上数据库,欢迎大家在评论区补充!

6. 参考文章

架构师深入解析Oracle BCV技术(oracle bcv)

Oracle 文件管理-参数文件、控制文件、归档 - 墨天轮

扩展一:控制文件中关于 Resetlogs 和 NoResetlogs 的区别

RESETLOGS 会重置在线重做日志文件,并重新开始日志序列号。通常在不完全恢复或数据库克隆时用。RESETLOGS之后,之前的日志和备份将不再有效,因此必须重新创建全备份。通常用在:不完全恢复、 数据库复制或克隆 、 备份丢失或不全的场景下。

NORESETLOGS 则保持现有的日志序列号,不会创建新的日志文件。通常在完全恢复时使用,能够继续使用现有的备份和日志文件,不需要立即重新备份数据库。

通常在不使用备份控制文件恢复的情况下,是可以使用 noresetlog 方式打开数据库的。 前提是不能丢失日志文件。假若丢失了控制文件和数据文件但还是想以 noresetlog打开的话,就必须手动以noresetlogs方式重建控制文件,而且redolog 的状态都必须正常

其他恢复情况:失控制文件及各种日志REDOLOG、所有的不完全恢复包括SCN,TIME,跨越 REDO,都必须使用 resetlogs,重置日志,肯定会丢数据,只能恢复到日志当前的数据。

在同步完测试库后,控制文件会去读数据文件头中与 CHECKPOINT SCN 对应的 RBA 信息来确定从那个序列的归档日志开始恢复,一直推进恢复到 NEXT SCN 是无穷大的那个 REDOLOG,此时恢复是完全恢复的,但打开的时候还要以 resetlogs 方式打开。

并且有些情况Oracle是允许以不一致的状态打开数据库,可以创建一份参数文件指定数据库的DBID,allow_resetlogs_corruption参数,手工起库,但这可能导致数据库进一步损坏。因此,此参数应仅在没有其他恢复选项且需要立即访问数据库时使用。

扩展二:local_listener 与 remote_listener 设置监听

1、LOCAL_LISTENER 参数配置

首先将监听的信息添加到 tnsnames.ora 文件中。 动态注册监听时要从 tnsnames.ora 中读取相关信息。

复制代码
LISTENER_PRODFS = (ADDRESS_LIST =
                   (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.66.101)(PORT = 1521))
                  )

然后以 sys 用戶修改 local_listener 参数:

复制代码
SQL> alter system set local_listener='LISTENER_PRODFS';

也可以不使用别名直接指定连接符(加服务器模式):

复制代码
QL> alter system set LOCAL_LISTENER='(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.66.101)(PORT = 1521))';

这样,在 DB 启动的时候,就会自动的把 instence_name 和 service_name 注册到监听。 如果在这期间,监听重启了,监听里的信息也会丢失,这时就需要手动的把信息注册到监听:

复制代码
SQL> alter system register;

2. REMOTE_LISTENER 参数配置

REMOTE_LISTENER 参数指定了远程监听器的地址,用于支持远程连接。配置远程监听器时,需要在 tnsnames.ora 文件中添加相应的监听器信息:

复制代码
LISTENERS_DB01 = (DESCRIPTION =
                  (ADDRESS_LIST =
   (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.66.101)(PORT = 1521))
   (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.66.102)(PORT = 1522))
  )
                 )

测试配置是否正确,可以使用 tnsping 命令:

复制代码
$ tnsping LISTENERS_DB01

在所有节点上设置远程监听器:

复制代码
SQL> ALTER SYSTEM SET REMOTE_LISTENER='LISTENERS_DB01' SCOPE=BOTH;

⭐此外还有还有一个参数`listener_networks`,用来增加一个监听用来使用专门的网络传输归档日志到DG库,这样不会影响业务。

参考MOS [ID 1063571.1 ]**:**How to Configure A Second Listener on a Separate Network in 11.2 Grid Infrastructure

扩展三:连接(访问)数据库的两种方式:LOCAL=NO 和 LOCAL=YES

在Oracle数据库中,连接到数据库可以通过两种主要方式:本地连接 (LOCAL=YES)和非本地连接(LOCAL=NO)。

  1. 非本地连接(LOCAL=NO)

    非本地连接,也称为网络连接,通过监听器(Listener)与数据库服务器进行通信。在这种方式下,客户端应用程序通过本地监听器将请求发送到服务器端监听器。服务器端监听器接收请求后,将其转发到数据库实例,数据库实例执行操作并将结果返回给客户端。因此,客户端需要配置监听器信息,通常在tnsnames.ora文件中进行设置。

  2. 本地连接(LOCAL=YES)

    本地连接直接在数据库服务器上进行,不经过网络监听器。在这种模式下,即使服务器上的监听器未启动, 通过本地的 sqlplus 还是可以连上数据库的 。

相关推荐
jnrjian5 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle
TTc_5 天前
oracle中的union和union all有什么区别?
数据库·oracle
山峰哥5 天前
吃透 SQL 优化:告别慢查询,解锁数据库高性能
服务器·数据库·sql·oracle·性能优化·编辑器
南 阳5 天前
Python从入门到精通day37
数据库·python·oracle
轩情吖5 天前
MySQL库的操作
android·数据库·mysql·oracle·字符集·数据库操作·编码集
脱发的老袁5 天前
【数据库】Oracle手动清理归档日志
数据库·oracle
jnrjian5 天前
Oracle 共享池 库缓存下的 Library Cache Lock
数据库·缓存·oracle
新缸中之脑6 天前
在Reddit上探索未满足的需求
数据库·oracle
light blue bird6 天前
产线多并发客户端指令操作场景组件
jvm·oracle·.net·winform
坐吃山猪6 天前
Neo4j04_数据库事务
数据库·oracle·neo4j