admin管理员组

文章数量:1530865

一,情况

1,发现问题

今天日常登录内部ERP系统,发现系统不能登录。

具体表现为:输入用户名和密码后,点击登录,系统没有响应。

2,系统表现

开始认为是ERP系统的程序出了问题,但登录应用服务器10.7之后发现,tomcat服务正常,ERP服务器进程运行正常,但日志不断出现新的报错信息。

查看日志,发现提示的都是数据库查询错误,因此判断是数据库问题。

本机使用PL/SQL工具连接数据库,进程进入假死状态,长期没有响应。

连接数据库服务器10.8,使用sqlplus登录数据库,可以正常登录。

本机使用PL/SQL工具,连接数据库,仍然出现程序假死的情况,没有响应。

由于昨天我在服务器上修改了memory_max_target和memory_target参数的值,从30G修改为20G,为了稳妥起见,先将服务器上的参数值再次改为了30G。

另外,由于10.8有一张网卡始终显示为 “正在识别 ”,因此将该网卡禁用了。

然而以上方式均没有起任何作用,还没有找到真正的问题。

百度发现可以使用tnsping命令测试服务器是否能够连接。

于是使用TNSPING,但没有结果,一直在等待。

C:\Users\Administrator>tnsping 192.168.10.8 orcl

TNS Ping Utility for 64-bit Windows: Version 11.2.0.1.0 - Production on 03-11月-2017 16:25:15

Copyright (c) 1997, 2010, Oracle. All rights reserved.

已使用的参数文件:

D:\app\Administrator\product\11.2.0\dbhome_1\network\admin\sqlnet.ora

已使用 EZCONNECT 适配器来解析别名

尝试连接 (DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.10.8)(PORT=1521)))

tnsping常用格式

tnsping IP:PORT/SID

tnsping IP SID

举例

tnsping 192.168.1.123:1521/oracle11g

tnsping 192.168.1.123 oracle11g

tnsping:

如果能够ping通,则说明客户端能解析listener的机器名,而且lister也已经启动,但是并不能说明数据库已经打开。

但是如果不能用tnsping通,则肯定连接不到数据库。

注意:tsnping的过程与真正客户端连接的过程并不一致。

通过Windows服务管理器,重启所有Oracle相关服务,但仍然无法连接。

这时注意到,当重启监听器服务时,PL/SQL程序立即出现了报错信息,提示没有监听器错误。

联想到之前的表现,初步能够确定是Oracle监听器出了问题,但重启监听器服务,甚至直接重启服务器,但均没有能够解决这个问题。

3,结果

再次百度,发现有人提到监听器由于日志满了而无法工作,联想到以前黄老师讲过,Oracle系统日志满了会导致数据库服务无法启动的情况,意识到服务器10.8很可能也是这种情况。

登录10.8,找到监听器日志文件夹,打开发现,日志文件大小已经达到4G。

将文件剪切到其他地方,重启服务器,系统可以正常连接。

二,反思

4,事后诸葛亮

心态:保持冷静,小心操作

当问题出现时,一定要保持冷静,分析问题,在确定问题的原因之前,应当尽量避免对数据库的修改。

如果条件允许,应先对所有的数据文件、日志文件做好备份。

做任何操作之前,先想好该操作应如何回滚或对冲操作。

目的:避免数据库的小问题变成大问题。

排查:注重逻辑,思路明确

根据问题的外在表现、Oracle运行原理等,初步确定问题范围

不断缩小问题范围,最终定位问题

确定问题原因

以本次问题为例,问题表现为

1, 在数据库服务器上通过sqlplus可以连接数据库,并且查到数据库为正常运行状态

2, 无论是服务器,还是客户端,使用PL/SQL软件不能连接,表现为软件发起连接数据库后,一直没有响应

3, 在服务器上sqlplus的@orcl连接方式无法连接数据库

4,想要通过expdp方式导出数据库,但命令长期无响应,此时是使用username/password@SID的方式连接数据库的

5,改为username/password方式,可以导出数据

综上可以判断,是监听器出现了问题。

知识点

在数据库服务器上有4种方式运行sqlplus,需要不同的监听器和服务器状态

1> sqlplus / as sysdba

1,不通过监听器,也不需要数据库处于运行状态

2> sqlplus username/password

2,不通过监听器,但需要数据库处于运行状态

3> sqlplus username/password@SID

4> sqlplus username/password@//host:port/sid

4(举例)> sqlplus userA/123@//192.168.100.100:1521/ORCL

3&4均通过网络连接,这时需要数据库服务器的listener处于监听状态,服务器需要处于运行状态。

此时建立一个连接的大致步骤如下

a. 查询sqlnet.ora,看看名称的解析方式,默认是TNSNAME

b. 查询tnsnames.ora文件,从里边找SID的记录,并且找到数据库服务器的主机名或者IP,端口和service_name

c. 如果服务器listener进程没有问题的话,建立与listener进程的连接。

d. 根据不同的服务器模式如专用服务器模式或者共享服务器模式,listener采取接下去的动作。默认是专用服务器模式,没有问题的话客户端就连接上了数据库的server process。

e. 这时连接已经建立,可以操作数据库了。

而PL/SQL软件通常都是通过第4种方式连接服务器,需要监听器处于监听状态,数据库处于运行状态,才能连接数据库。

经百度,发现在Windows环境下,Oracle的日志如果达到4G大小,Oracle就会无法继续写日志,从而导致Oracle及其服务不能正常工作。

自身需要增加知识储备

对Oracle数据库的架构、运行机制有一定了解(监听器,数据库例程,客户端 / 服务器通话机制,后台进程工作原理等)

掌握查找问题的服务器状态指标、查找方法(命令、脚本等)

Oracle日志的作用、位置,通过日志定位问题的方法

解决:解决问题,并尽可能避免再次发生

解决问题

通过oerr命令查看错误提示(Linux系统自带,Windows需要自己下载)

查看Oracle的相关技术文档(Oracle网站或下载到本地的文档)

通过搜索引擎,查找解决办法

避免问题再次发生

系统设置方面的错误,改为正确设置,定期检查

需要定期处理的问题(例如日志等),可以通过定时任务,按照规则对日志做处理(例如,定期复制到其他位置并按规则命名,原地重建空日志文件)

硬件问题(如磁盘空间不够等),需要定期检查或者自动报警等方式监控(如Nagios等),提前准备硬件设备。

5,Oracle监听器日志知识相关博客

博客作者:潇湘隐者(他的博客)

博客摘录:

要对监听日志文件(listener.log)进行定期清理,如果不定期清理,会遇到下面一些麻烦:

1:监听日志文件(listener.log)变得越来越大,占用额外的存储空间。(当然现在存储白菜价,不差那几G的空间。但是我们还是要本着工匠情怀,精益求精)

2:监听日志文件(listener.log)变得太大会带来一些问题:LISTENER.LOG日志大小不能超过2GB,超过会导致LISTENER监听器无法处理新的连接。

3:监听日志文件(listener.log)变得太大,给后续日志写入带来一些性能问题和麻烦。

4:在一个很大的监听日志文件(listener.log)中查找某一天或某一个错误,这个也会带来一些性能问题,查找起来也相当麻烦。

所以应该定期对监听日志文件(listener.log)进行清理,另外一种说法叫截断日志文件。

关于截断监听日志,要注意一些问题。初学ORACLE的时候遇到一个错误的截断监听日志的,演示如下

[oracle@DB-Server log]$ mv listener.log listener.log.20150114

[oracle@DB-Server log]$ cp /dev/null listener.log

[oracle@DB-Server log]$ more listener.log

这样截断监听日志(listener.log)后,监听服务进程(tnslsnr)并不会将新的监听信息写入listener.log,而是继续写入listener.log.20150114

规范正确的流程应该这么处理:

Step 1:首先停止监听服务进程(tnslsnr)记录日志。

[oracle@DB-Server log]$ lsnrctl set log_status off;

Step 2:将监听日志文件(listener.log)复制一份,以listener.log.yyyymmdd格式命名

[oracle@DB-Server log]$ cp listener.log listener.log.20150114

Step 3:将监听日志文件(listener.log)清空。清空文件的方法有很多

3.1 echo “” > filename

3.2 cp /dev/null 或 echo /dev/null > filename

Step 4:开启监听服务进程(tnslsnr)记录日志

[oracle@DB-Server log]$ lsnrctl set log_status on;

当然也可以直接移走监听日志文件(listener.log),数据库实例会自动创建一个listener.log文件。

% lsnrctl set log_status off

% mv listener.log listener.yyyymmdd

% lsnrctl set log_status on

这些操作应该通过shell脚本来处理,然后结合crontab作业定期清理、截断监听日志文件。例如网上的一个清理、截断监听日志文件的shell脚本。

rq=` date +"%d" `

cp $ORACLE_HOME/network/log/listener.log $ORACLE_BACKUP/network/log/listener_$rq.log

su - oracle -c "lsnrctl set log_status off"

cp /dev/null $ORACLE_HOME/network/log/listener.log

su - oracle -c "lsnrctl set log_status on"

但这样的脚本还没有解决一个问题,就是截断的监听日志文件保留多久的问题。

比如我只想保留这些截断的监听日志一个月时间,我希望作业自动维护。不需要我去手工操作。

有这样一个脚本cls_oracle.sh可以完全做到这个,当然它还会归档、清理其它日志文件,例如告警文件(alert_sid.log)等等。功能非常强大。

脚本代码及使用方法请见原博客

本文标签: 日志静态发现ORACLE